···11+From 6b3ab4a94e4d498cdabd5aac6b749031abd785c8 Mon Sep 17 00:00:00 2001
22+From: Ralph Meijer <ralphm@ik.nu>
33+Date: Thu, 18 Jul 2024 19:04:47 +0200
44+Subject: [PATCH] Remove py2 compat
55+66+Co-authored-by: OPNA2608 <opna2608@protonmail.com>
77+---
88+ setup.py | 11 ++-
99+ wokkel/component.py | 13 ++-
1010+ wokkel/data_form.py | 70 ++++++----------
1111+ wokkel/delay.py | 2 +-
1212+ wokkel/disco.py | 51 ++++++------
1313+ wokkel/formats.py | 20 ++---
1414+ wokkel/generic.py | 19 +----
1515+ wokkel/iwokkel.py | 150 +++++++++++++++++-----------------
1616+ wokkel/muc.py | 67 ++++++++-------
1717+ wokkel/pubsub.py | 55 ++++++-------
1818+ wokkel/server.py | 17 ++--
1919+ wokkel/shim.py | 5 +-
2020+ wokkel/subprotocols.py | 13 ++-
2121+ wokkel/test/helpers.py | 5 +-
2222+ wokkel/test/test_client.py | 3 +-
2323+ wokkel/test/test_data_form.py | 89 +++++---------------
2424+ wokkel/test/test_generic.py | 75 +----------------
2525+ wokkel/test/test_muc.py | 13 ++-
2626+ wokkel/test/test_server.py | 6 +-
2727+ wokkel/test/test_shim.py | 5 +-
2828+ wokkel/test/test_xmppim.py | 19 ++---
2929+ wokkel/xmppim.py | 89 ++++++++++----------
3030+ 22 files changed, 318 insertions(+), 479 deletions(-)
3131+3232+diff --git a/setup.py b/setup.py
3333+index 8804fd9..f7f1e33 100755
3434+--- a/setup.py
3535++++ b/setup.py
3636+@@ -40,11 +40,11 @@ setup(name='wokkel',
3737+ license='MIT',
3838+ platforms='any',
3939+ classifiers=[
4040+- 'Programming Language :: Python :: 2.7',
4141+ 'Programming Language :: Python :: 3',
4242+- 'Programming Language :: Python :: 3.4',
4343+- 'Programming Language :: Python :: 3.5',
4444+ 'Programming Language :: Python :: 3.6',
4545++ 'Programming Language :: Python :: 3.7',
4646++ 'Programming Language :: Python :: 3.8',
4747++ 'Programming Language :: Python :: 3.9',
4848+ ],
4949+ packages=[
5050+ 'wokkel',
5151+@@ -60,16 +60,15 @@ setup(name='wokkel',
5252+ install_requires=[
5353+ 'incremental>=16.9.0',
5454+ 'python-dateutil',
5555++ 'Twisted[tls]>=16.4.0',
5656+ ],
5757+ extras_require={
5858+- ":python_version<'3'": 'Twisted[tls]>=15.5.0',
5959+- ":python_version>'3'": 'Twisted[tls]>=16.4.0',
6060+ "dev": [
6161+ "pyflakes",
6262+ "coverage",
6363++ "pydoctor",
6464+ "sphinx",
6565+ "towncrier",
6666+ ],
6767+- "dev:python_version<'3'": "pydoctor",
6868+ },
6969+ )
7070+diff --git a/wokkel/component.py b/wokkel/component.py
7171+index da48230..9410837 100644
7272+--- a/wokkel/component.py
7373++++ b/wokkel/component.py
7474+@@ -12,7 +12,6 @@ from __future__ import division, absolute_import
7575+ from twisted.application import service
7676+ from twisted.internet import reactor
7777+ from twisted.python import log
7878+-from twisted.python.compat import unicode
7979+ from twisted.words.protocols.jabber.jid import internJID as JID
8080+ from twisted.words.protocols.jabber import component, error, xmlstream
8181+ from twisted.words.xish import domish
8282+@@ -105,7 +104,7 @@ class InternalComponent(xmlstream.XMPPHandlerCollection, service.Service):
8383+ components of this type connect to a router in the same process. This
8484+ allows for one-process XMPP servers.
8585+8686+- @ivar domains: Domains (as L{unicode}) this component will handle traffic
8787++ @ivar domains: Domains (as L{str}) this component will handle traffic
8888+ for.
8989+ @type domains: L{set}
9090+ """
9191+@@ -177,7 +176,7 @@ class ListenComponentAuthenticator(xmlstream.ListenAuthenticator):
9292+ Authenticator for accepting components.
9393+9494+ @ivar secret: The shared used to authorized incoming component connections.
9595+- @type secret: L{unicode}.
9696++ @type secret: L{str}.
9797+ """
9898+9999+ namespace = NS_COMPONENT_ACCEPT
100100+@@ -241,7 +240,7 @@ class ListenComponentAuthenticator(xmlstream.ListenAuthenticator):
101101+ L{onHandshake}.
102102+ """
103103+ if (element.uri, element.name) == (self.namespace, 'handshake'):
104104+- self.onHandshake(unicode(element))
105105++ self.onHandshake(str(element))
106106+ else:
107107+ exc = error.StreamError('not-authorized')
108108+ self.xmlstream.sendStreamError(exc)
109109+@@ -257,7 +256,7 @@ class ListenComponentAuthenticator(xmlstream.ListenAuthenticator):
110110+ be exchanged.
111111+ """
112112+ calculatedHash = xmlstream.hashPassword(self.xmlstream.sid,
113113+- unicode(self.secret))
114114++ str(self.secret))
115115+ if handshake != calculatedHash:
116116+ exc = error.StreamError('not-authorized', text='Invalid hash')
117117+ self.xmlstream.sendStreamError(exc)
118118+@@ -301,7 +300,7 @@ class Router(object):
119119+120120+ @param destination: Destination of the route to be added as a host name
121121+ or L{None} for the default route.
122122+- @type destination: L{unicode} or L{NoneType}
123123++ @type destination: L{str} or L{NoneType}
124124+125125+ @param xs: XML Stream to register the route for.
126126+ @type xs:
127127+@@ -316,7 +315,7 @@ class Router(object):
128128+ Remove a route.
129129+130130+ @param destination: Destination of the route that should be removed.
131131+- @type destination: L{unicode}
132132++ @type destination: L{str}
133133+134134+ @param xs: XML Stream to remove the route for.
135135+ @type xs:
136136+diff --git a/wokkel/data_form.py b/wokkel/data_form.py
137137+index ed9c5fc..7f1c34c 100644
138138+--- a/wokkel/data_form.py
139139++++ b/wokkel/data_form.py
140140+@@ -17,7 +17,6 @@ from __future__ import division, absolute_import
141141+ from zope.interface import implementer
142142+ from zope.interface.common import mapping
143143+144144+-from twisted.python.compat import iteritems, unicode, _PY3
145145+ from twisted.words.protocols.jabber.jid import JID
146146+ from twisted.words.xish import domish
147147+148148+@@ -51,9 +50,9 @@ class Option(object):
149149+ Data Forms field option.
150150+151151+ @ivar value: Value of this option.
152152+- @type value: L{unicode}
153153++ @type value: L{str}
154154+ @ivar label: Optional label for this option.
155155+- @type label: L{unicode} or L{NoneType}
156156++ @type label: L{str} or L{NoneType}
157157+ """
158158+159159+ def __init__(self, value, label=None):
160160+@@ -91,7 +90,7 @@ class Option(object):
161161+ raise Error("Option has no value")
162162+163163+ label = element.getAttribute('label')
164164+- return Option(unicode(valueElements[0]), label)
165165++ return Option(str(valueElements[0]), label)
166166+167167+168168+ class Field(object):
169169+@@ -108,15 +107,15 @@ class Field(object):
170170+ @ivar var: Field name. Optional if C{fieldType} is C{'fixed'}.
171171+ @type var: L{str}
172172+ @ivar label: Human readable label for this field.
173173+- @type label: L{unicode}
174174++ @type label: L{str}
175175+ @ivar values: The values for this field, for multi-valued field
176176+- types, as a list of L{bool}, L{unicode} or L{JID}.
177177++ types, as a list of L{bool}, L{str} or L{JID}.
178178+ @type values: L{list}
179179+ @ivar options: List of possible values to choose from in a response
180180+ to this form as a list of L{Option}s.
181181+ @type options: L{list}
182182+ @ivar desc: Human readable description for this field.
183183+- @type desc: L{unicode}
184184++ @type desc: L{str}
185185+ @ivar required: Whether the field is required to be provided in a
186186+ response to this form.
187187+ @type required: L{bool}
188188+@@ -147,7 +146,7 @@ class Field(object):
189189+ try:
190190+ self.options = [Option(optionValue, optionLabel)
191191+ for optionValue, optionLabel
192192+- in iteritems(options)]
193193++ in options.items()]
194194+ except AttributeError:
195195+ self.options = options or []
196196+197197+@@ -185,7 +184,7 @@ class Field(object):
198198+199199+ Sets C{value} as the only element of L{values}.
200200+201201+- @type value: L{bool}, L{unicode} or L{JID}
202202++ @type value: L{bool}, L{str} or L{JID}
203203+ """
204204+ self.values = [value]
205205+206206+@@ -229,7 +228,7 @@ class Field(object):
207207+ newValues = []
208208+ for value in self.values:
209209+ if self.fieldType == 'boolean':
210210+- if isinstance(value, (str, unicode)):
211211++ if isinstance(value, str):
212212+ checkValue = value.lower()
213213+ if not checkValue in ('0', '1', 'false', 'true'):
214214+ raise ValueError("Not a boolean")
215215+@@ -263,9 +262,9 @@ class Field(object):
216216+217217+ for value in self.values:
218218+ if isinstance(value, bool):
219219+- value = unicode(value).lower()
220220++ value = str(value).lower()
221221+ else:
222222+- value = unicode(value)
223223++ value = str(value)
224224+225225+ field.addElement('value', content=value)
226226+227227+@@ -288,7 +287,7 @@ class Field(object):
228228+229229+ @staticmethod
230230+ def _parse_desc(field, element):
231231+- desc = unicode(element)
232232++ desc = str(element)
233233+ if desc:
234234+ field.desc = desc
235235+236236+@@ -305,7 +304,7 @@ class Field(object):
237237+238238+ @staticmethod
239239+ def _parse_value(field, element):
240240+- value = unicode(element)
241241++ value = str(element)
242242+ field.values.append(value)
243243+244244+245245+@@ -313,9 +312,9 @@ class Field(object):
246246+ def fromElement(element):
247247+ field = Field(None)
248248+249249+- for eAttr, fAttr in iteritems({'type': 'fieldType',
250250+- 'var': 'var',
251251+- 'label': 'label'}):
252252++ for eAttr, fAttr in {'type': 'fieldType',
253253++ 'var': 'var',
254254++ 'label': 'label'}.items():
255255+ value = element.getAttribute(eAttr)
256256+ if value:
257257+ setattr(field, fAttr, value)
258258+@@ -350,7 +349,7 @@ class Field(object):
259259+260260+ if 'options' in fieldDict:
261261+ options = []
262262+- for value, label in iteritems(fieldDict['options']):
263263++ for value, label in fieldDict['options'].items():
264264+ options.append(Option(value, label))
265265+ kwargs['options'] = options
266266+267267+@@ -385,9 +384,9 @@ class Form(object):
268268+ @type formType: L{str}
269269+270270+ @ivar title: Natural language title of the form.
271271+- @type title: L{unicode}
272272++ @type title: L{str}
273273+274274+- @ivar instructions: Natural language instructions as a list of L{unicode}
275275++ @ivar instructions: Natural language instructions as a list of L{str}
276276+ strings without line breaks.
277277+ @type instructions: L{list}
278278+279279+@@ -497,7 +496,7 @@ class Form(object):
280280+ C{fieldDefs}.
281281+ @type filterUnknown: L{bool}
282282+ """
283283+- for name, value in iteritems(values):
284284++ for name, value in values.items():
285285+ fieldDict = {'var': name,
286286+ 'type': None}
287287+288288+@@ -542,14 +541,14 @@ class Form(object):
289289+290290+ @staticmethod
291291+ def _parse_title(form, element):
292292+- title = unicode(element)
293293++ title = str(element)
294294+ if title:
295295+ form.title = title
296296+297297+298298+ @staticmethod
299299+ def _parse_instructions(form, element):
300300+- instructions = unicode(element)
301301++ instructions = str(element)
302302+ if instructions:
303303+ form.instructions.append(instructions)
304304+305305+@@ -624,36 +623,19 @@ class Form(object):
306306+ return key in self.fields
307307+308308+309309+- def iterkeys(self):
310310++ def keys(self):
311311+ return iter(self)
312312+313313+314314+- def itervalues(self):
315315++ def values(self):
316316+ for key in self:
317317+ yield self[key]
318318+319319+320320+- def iteritems(self):
321321++ def items(self):
322322+ for key in self:
323323+ yield (key, self[key])
324324+325325+- if _PY3:
326326+- keys = iterkeys
327327+- values = itervalues
328328+- items = iteritems
329329+- else:
330330+- def keys(self):
331331+- return list(self)
332332+-
333333+-
334334+- def values(self):
335335+- return list(self.itervalues())
336336+-
337337+-
338338+- def items(self):
339339+- return list(self.iteritems())
340340+-
341341+-
342342+ def getValues(self):
343343+ """
344344+ Extract values from the named form fields.
345345+@@ -701,7 +683,7 @@ class Form(object):
346346+347347+ filtered = []
348348+349349+- for name, field in iteritems(self.fields):
350350++ for name, field in self.fields.items():
351351+ if name in fieldDefs:
352352+ fieldDef = fieldDefs[name]
353353+ if 'type' not in fieldDef:
354354+diff --git a/wokkel/delay.py b/wokkel/delay.py
355355+index be06cb3..1dd1703 100644
356356+--- a/wokkel/delay.py
357357++++ b/wokkel/delay.py
358358+@@ -46,7 +46,7 @@ class Delay(object):
359359+ Render this instance into a domish Element.
360360+361361+ @param legacy: If C{True}, use the legacy XEP-0091 format.
362362+- @type legacy: C{bool}
363363++ @type legacy: L{bool}
364364+ """
365365+ if not self.stamp:
366366+ raise ValueError("stamp is required")
367367+diff --git a/wokkel/disco.py b/wokkel/disco.py
368368+index 9ea43ef..227789d 100644
369369+--- a/wokkel/disco.py
370370++++ b/wokkel/disco.py
371371+@@ -13,7 +13,6 @@ U{XEP-0030<http://xmpp.org/extensions/xep-0030.html>}.
372372+ from __future__ import division, absolute_import
373373+374374+ from twisted.internet import defer
375375+-from twisted.python.compat import iteritems, unicode
376376+ from twisted.words.protocols.jabber import error, jid
377377+ from twisted.words.xish import domish
378378+379379+@@ -29,11 +28,11 @@ IQ_GET = '/iq[@type="get"]'
380380+ DISCO_INFO = IQ_GET + '/query[@xmlns="' + NS_DISCO_INFO + '"]'
381381+ DISCO_ITEMS = IQ_GET + '/query[@xmlns="' + NS_DISCO_ITEMS + '"]'
382382+383383+-class DiscoFeature(unicode):
384384++class DiscoFeature(str):
385385+ """
386386+ XMPP service discovery feature.
387387+388388+- This extends C{unicode} to convert to and from L{domish.Element}, but
389389++ This extends L{str} to convert to and from L{domish.Element}, but
390390+ further behaves identically.
391391+ """
392392+393393+@@ -44,7 +43,7 @@ class DiscoFeature(unicode):
394394+ @rtype: L{domish.Element}.
395395+ """
396396+ element = domish.Element((NS_DISCO_INFO, 'feature'))
397397+- element['var'] = unicode(self)
398398++ element['var'] = str(self)
399399+ return element
400400+401401+402402+@@ -68,11 +67,11 @@ class DiscoIdentity(object):
403403+ XMPP service discovery identity.
404404+405405+ @ivar category: The identity category.
406406+- @type category: C{unicode}
407407++ @type category: L{str}
408408+ @ivar type: The identity type.
409409+- @type type: C{unicode}
410410++ @type type: L{str}
411411+ @ivar name: The optional natural language name for this entity.
412412+- @type name: C{unicode}
413413++ @type name: L{str}
414414+ """
415415+416416+ def __init__(self, category, idType, name=None):
417417+@@ -119,21 +118,21 @@ class DiscoInfo(object):
418418+ XMPP service discovery info.
419419+420420+ @ivar nodeIdentifier: The optional node this info applies to.
421421+- @type nodeIdentifier: C{unicode}
422422++ @type nodeIdentifier: L{str}
423423+ @ivar features: Features as L{DiscoFeature}.
424424+- @type features: C{set}
425425++ @type features: L{set}
426426+ @ivar identities: Identities as a mapping from (category, type) to name,
427427+- all C{unicode}.
428428+- @type identities: C{dict}
429429++ all L{str}.
430430++ @type identities: L{dict}
431431+ @ivar extensions: Service discovery extensions as a mapping from the
432432+- extension form's C{FORM_TYPE} (C{unicode}) to
433433++ extension form's C{FORM_TYPE} (L{str}) to
434434+ L{data_form.Form}. Forms with no C{FORM_TYPE} field
435435+ are mapped as C{None}. Note that multiple forms
436436+ with the same C{FORM_TYPE} have the last in sequence
437437+ prevail.
438438+- @type extensions: C{dict}
439439++ @type extensions: L{dict}
440440+ @ivar _items: Sequence of added items.
441441+- @type _items: C{list}
442442++ @type _items: L{list}
443443+ """
444444+445445+ def __init__(self):
446446+@@ -226,9 +225,9 @@ class DiscoItem(object):
447447+ @ivar entity: The entity holding the item.
448448+ @type entity: L{jid.JID}
449449+ @ivar nodeIdentifier: The optional node identifier for the item.
450450+- @type nodeIdentifier: C{unicode}
451451++ @type nodeIdentifier: L{str}
452452+ @ivar name: The optional natural language name for this entity.
453453+- @type name: C{unicode}
454454++ @type name: L{str}
455455+ """
456456+457457+ def __init__(self, entity, nodeIdentifier='', name=None):
458458+@@ -278,9 +277,9 @@ class DiscoItems(object):
459459+ XMPP service discovery items.
460460+461461+ @ivar nodeIdentifier: The optional node this info applies to.
462462+- @type nodeIdentifier: C{unicode}
463463++ @type nodeIdentifier: L{str}
464464+ @ivar _items: Sequence of added items.
465465+- @type _items: C{list}
466466++ @type _items: L{list}
467467+ """
468468+469469+ def __init__(self):
470470+@@ -353,9 +352,9 @@ class _DiscoRequest(generic.Request):
471471+ A Service Discovery request.
472472+473473+ @ivar verb: Type of request: C{'info'} or C{'items'}.
474474+- @type verb: C{str}
475475++ @type verb: L{str}
476476+ @ivar nodeIdentifier: Optional node to request info for.
477477+- @type nodeIdentifier: C{unicode}
478478++ @type nodeIdentifier: L{str}
479479+ """
480480+481481+ verb = None
482482+@@ -366,7 +365,7 @@ class _DiscoRequest(generic.Request):
483483+ NS_DISCO_ITEMS: 'items',
484484+ }
485485+486486+- _verbRequestMap = dict(((v, k) for k, v in iteritems(_requestVerbMap)))
487487++ _verbRequestMap = dict(((v, k) for k, v in _requestVerbMap.items()))
488488+489489+ def __init__(self, verb=None, nodeIdentifier='',
490490+ recipient=None, sender=None):
491491+@@ -415,7 +414,7 @@ class DiscoClientProtocol(XMPPHandler):
492492+ @type entity: L{jid.JID}
493493+494494+ @param nodeIdentifier: Optional node to request info from.
495495+- @type nodeIdentifier: C{unicode}
496496++ @type nodeIdentifier: L{str}
497497+498498+ @param sender: Optional sender address.
499499+ @type sender: L{jid.JID}
500500+@@ -438,7 +437,7 @@ class DiscoClientProtocol(XMPPHandler):
501501+ @type entity: L{jid.JID}
502502+503503+ @param nodeIdentifier: Optional node to request info from.
504504+- @type nodeIdentifier: C{unicode}
505505++ @type nodeIdentifier: L{str}
506506+507507+ @param sender: Optional sender address.
508508+ @type sender: L{jid.JID}
509509+@@ -534,7 +533,7 @@ class DiscoHandler(XMPPHandler, IQHandlerMixin):
510510+511511+ @param deferredList: List of deferreds for which the results should be
512512+ gathered.
513513+- @type deferredList: C{list}
514514++ @type deferredList: L{list}
515515+ @return: Deferred that fires with a list of gathered results.
516516+ @rtype: L{defer.Deferred}
517517+ """
518518+@@ -566,7 +565,7 @@ class DiscoHandler(XMPPHandler, IQHandlerMixin):
519519+ @param target: The entity the request was sent to.
520520+ @type target: L{JID<twisted.words.protocols.jabber.jid.JID>}
521521+ @param nodeIdentifier: The optional node being queried, or C{''}.
522522+- @type nodeIdentifier: C{unicode}
523523++ @type nodeIdentifier: L{str}
524524+ @return: Deferred with the gathered results from sibling handlers.
525525+ @rtype: L{defer.Deferred}
526526+ """
527527+@@ -589,7 +588,7 @@ class DiscoHandler(XMPPHandler, IQHandlerMixin):
528528+ @param target: The entity the request was sent to.
529529+ @type target: L{JID<twisted.words.protocols.jabber.jid.JID>}
530530+ @param nodeIdentifier: The optional node being queried, or C{''}.
531531+- @type nodeIdentifier: C{unicode}
532532++ @type nodeIdentifier: L{str}
533533+ @return: Deferred with the gathered results from sibling handlers.
534534+ @rtype: L{defer.Deferred}
535535+ """
536536+diff --git a/wokkel/formats.py b/wokkel/formats.py
537537+index 0eb0be6..972cc7e 100644
538538+--- a/wokkel/formats.py
539539++++ b/wokkel/formats.py
540540+@@ -9,8 +9,6 @@ Generic payload formats.
541541+542542+ from __future__ import division, absolute_import
543543+544544+-from twisted.python.compat import unicode
545545+-
546546+ NS_MOOD = 'http://jabber.org/protocol/mood'
547547+ NS_TUNE = 'http://jabber.org/protocol/tune'
548548+549549+@@ -55,7 +53,7 @@ class Mood:
550550+ continue
551551+552552+ if child.name == 'text':
553553+- text = unicode(child)
554554++ text = str(child)
555555+ else:
556556+ value = child.name
557557+558558+@@ -76,19 +74,19 @@ class Tune:
559559+ U{XEP-0118<http://xmpp.org/extensions/xep-0118.html>}.
560560+561561+ @ivar artist: The artist or performer of the song or piece.
562562+- @type artist: C{unicode}
563563++ @type artist: L{str}
564564+ @ivar length: The duration of the song or piece in seconds.
565565+- @type length: C{int}
566566++ @type length: L{int}
567567+ @ivar source: The collection (e.g. album) or other source.
568568+- @type source: C{unicode}
569569++ @type source: L{str}
570570+ @ivar title: The title of the song or piece
571571+- @type title: C{unicode}
572572++ @type title: L{str}
573573+ @ivar track: A unique identifier for the tune; e.g. the track number within
574574+ the collection or the specific URI for the object.
575575+- @type track: C{unicode}
576576++ @type track: L{str}
577577+ @ivar uri: A URI pointing to information about the song, collection, or
578578+ artist.
579579+- @type uri: C{str}
580580++ @type uri: L{str}
581581+582582+ """
583583+584584+@@ -122,10 +120,10 @@ class Tune:
585585+ continue
586586+587587+ if child.name in ('artist', 'source', 'title', 'track', 'uri'):
588588+- setattr(tune, child.name, unicode(child))
589589++ setattr(tune, child.name, str(child))
590590+ elif child.name == 'length':
591591+ try:
592592+- tune.length = int(unicode(child))
593593++ tune.length = int(str(child))
594594+ except ValueError:
595595+ pass
596596+597597+diff --git a/wokkel/generic.py b/wokkel/generic.py
598598+index 2e975f6..becff8f 100644
599599+--- a/wokkel/generic.py
600600++++ b/wokkel/generic.py
601601+@@ -13,14 +13,11 @@ from zope.interface import implementer
602602+603603+ from twisted.internet import defer, protocol
604604+ from twisted.python import reflect
605605+-from twisted.python.deprecate import deprecated
606606+ from twisted.words.protocols.jabber import error, jid, xmlstream
607607+ from twisted.words.protocols.jabber.xmlstream import toResponse
608608+ from twisted.words.xish import domish, utility
609609+ from twisted.words.xish.xmlstream import BootstrapMixin
610610+611611+-from incremental import Version
612612+-
613613+ from wokkel.iwokkel import IDisco
614614+ from wokkel.subprotocols import XMPPHandler
615615+616616+@@ -35,7 +32,7 @@ def parseXml(string):
617617+ Parse serialized XML into a DOM structure.
618618+619619+ @param string: The serialized XML to be parsed, UTF-8 encoded.
620620+- @type string: C{str}.
621621++ @type string: L{str}.
622622+ @return: The DOM structure, or C{None} on empty or incomplete input.
623623+ @rtype: L{domish.Element}
624624+ """
625625+@@ -332,17 +329,3 @@ class DeferredXmlStreamFactory(BootstrapMixin, protocol.ClientFactory):
626626+627627+ def clientConnectionFailed(self, connector, reason):
628628+ self.deferred.errback(reason)
629629+-
630630+-
631631+-
632632+-@deprecated(Version("wokkel", 18, 0, 0), "unicode.encode('idna')")
633633+-def prepareIDNName(name):
634634+- """
635635+- Encode a unicode IDN Domain Name into its ACE equivalent.
636636+-
637637+- This will encode the domain labels, separated by allowed dot code points,
638638+- to their ASCII Compatible Encoding (ACE) equivalent, using punycode. The
639639+- result is an ASCII byte string of the encoded labels, separated by the
640640+- standard full stop.
641641+- """
642642+- return name.encode('idna')
643643+diff --git a/wokkel/iwokkel.py b/wokkel/iwokkel.py
644644+index 30a1057..35383b5 100644
645645+--- a/wokkel/iwokkel.py
646646++++ b/wokkel/iwokkel.py
647647+@@ -46,7 +46,7 @@ class IDisco(Interface):
648648+ @param nodeIdentifier: The optional identifier of the node at this
649649+ entity to retrieve the identify and features of. The default is
650650+ C{''}, meaning the root node.
651651+- @type nodeIdentifier: C{unicode}
652652++ @type nodeIdentifier: L{str}
653653+ """
654654+655655+ def getDiscoItems(requestor, target, nodeIdentifier=''):
656656+@@ -60,7 +60,7 @@ class IDisco(Interface):
657657+ @param nodeIdentifier: The optional identifier of the node at this
658658+ entity to retrieve the identify and features of.
659659+ The default is C{''}, meaning the root node.
660660+- @type nodeIdentifier: C{unicode}
661661++ @type nodeIdentifier: L{str}
662662+ """
663663+664664+665665+@@ -109,7 +109,7 @@ class IPubSubClient(Interface):
666666+ @param nodeIdentifier: Optional suggestion for the new node's
667667+ identifier. If omitted, the creation of an
668668+ instant node will be attempted.
669669+- @type nodeIdentifier: C{unicode}
670670++ @type nodeIdentifier: L{str}
671671+ @return: a deferred that fires with the identifier of the newly created
672672+ node. Note that this can differ from the suggested identifier
673673+ if the publish subscribe service chooses to modify or ignore
674674+@@ -124,7 +124,7 @@ class IPubSubClient(Interface):
675675+ @param service: The publish-subscribe service entity.
676676+ @type service: L{JID<twisted.words.protocols.jabber.jid.JID>}
677677+ @param nodeIdentifier: Identifier of the node to be deleted.
678678+- @type nodeIdentifier: C{unicode}
679679++ @type nodeIdentifier: L{str}
680680+ @rtype: L{Deferred<twisted.internet.defer.Deferred>}
681681+ """
682682+683683+@@ -135,7 +135,7 @@ class IPubSubClient(Interface):
684684+ @param service: The publish-subscribe service entity.
685685+ @type service: L{JID<twisted.words.protocols.jabber.jid.JID>}
686686+ @param nodeIdentifier: Identifier of the node to subscribe to.
687687+- @type nodeIdentifier: C{unicode}
688688++ @type nodeIdentifier: L{str}
689689+ @param subscriber: JID to subscribe to the node.
690690+ @type subscriber: L{JID<twisted.words.protocols.jabber.jid.JID>}
691691+ @rtype: L{Deferred<twisted.internet.defer.Deferred>}
692692+@@ -148,7 +148,7 @@ class IPubSubClient(Interface):
693693+ @param service: The publish-subscribe service entity.
694694+ @type service: L{JID<twisted.words.protocols.jabber.jid.JID>}
695695+ @param nodeIdentifier: Identifier of the node to unsubscribe from.
696696+- @type nodeIdentifier: C{unicode}
697697++ @type nodeIdentifier: L{str}
698698+ @param subscriber: JID to unsubscribe from the node.
699699+ @type subscriber: L{JID<twisted.words.protocols.jabber.jid.JID>}
700700+ @rtype: L{Deferred<twisted.internet.defer.Deferred>}
701701+@@ -165,9 +165,9 @@ class IPubSubClient(Interface):
702702+ @param service: The publish-subscribe service entity.
703703+ @type service: L{JID<twisted.words.protocols.jabber.jid.JID>}
704704+ @param nodeIdentifier: Identifier of the node to publish to.
705705+- @type nodeIdentifier: C{unicode}
706706++ @type nodeIdentifier: L{str}
707707+ @param items: List of item elements.
708708+- @type items: C{list} of L{Item}
709709++ @type items: L{list} of L{Item}
710710+ @rtype: L{Deferred<twisted.internet.defer.Deferred>}
711711+ """
712712+713713+@@ -191,12 +191,12 @@ class IPubSubService(Interface):
714714+ @type service: L{JID<twisted.words.protocols.jabber.jid.JID>}
715715+ @param nodeIdentifier: The identifier of the node that was published
716716+ to.
717717+- @type nodeIdentifier: C{unicode}
718718++ @type nodeIdentifier: L{str}
719719+ @param notifications: The notifications as tuples of subscriber, the
720720+ list of subscriptions and the list of items to be notified.
721721+- @type notifications: C{list} of
722722+- (L{JID<twisted.words.protocols.jabber.jid.JID>}, C{list} of
723723+- L{Subscription<wokkel.pubsub.Subscription>}, C{list} of
724724++ @type notifications: L{list} of
725725++ (L{JID<twisted.words.protocols.jabber.jid.JID>}, L{list} of
726726++ L{Subscription<wokkel.pubsub.Subscription>}, L{list} of
727727+ L{Element<twisted.words.xish.domish.Element>})
728728+ """
729729+730730+@@ -209,14 +209,14 @@ class IPubSubService(Interface):
731731+ @param service: The entity the notifications will originate from.
732732+ @type service: L{JID<twisted.words.protocols.jabber.jid.JID>}
733733+ @param nodeIdentifier: The identifier of the node that was deleted.
734734+- @type nodeIdentifier: C{unicode}
735735++ @type nodeIdentifier: L{str}
736736+ @param subscribers: The subscribers for which a notification should be
737737+ sent out.
738738+- @type subscribers: C{list} of
739739++ @type subscribers: L{list} of
740740+ L{JID<twisted.words.protocols.jabber.jid.JID>}
741741+ @param redirectURI: Optional XMPP URI of another node that subscribers
742742+ are redirected to.
743743+- @type redirectURI: C{str}
744744++ @type redirectURI: L{str}
745745+ """
746746+747747+ def publish(requestor, service, nodeIdentifier, items):
748748+@@ -228,9 +228,9 @@ class IPubSubService(Interface):
749749+ @param service: The entity the request was addressed to.
750750+ @type service: L{JID<twisted.words.protocols.jabber.jid.JID>}
751751+ @param nodeIdentifier: The identifier of the node to publish to.
752752+- @type nodeIdentifier: C{unicode}
753753++ @type nodeIdentifier: L{str}
754754+ @param items: The items to be published as elements.
755755+- @type items: C{list} of C{Element<twisted.words.xish.domish.Element>}
756756++ @type items: L{list} of C{Element<twisted.words.xish.domish.Element>}
757757+ @return: deferred that fires on success.
758758+ @rtype: L{Deferred<twisted.internet.defer.Deferred>}
759759+ """
760760+@@ -244,7 +244,7 @@ class IPubSubService(Interface):
761761+ @param service: The entity the request was addressed to.
762762+ @type service: L{JID<twisted.words.protocols.jabber.jid.JID>}
763763+ @param nodeIdentifier: The identifier of the node to subscribe to.
764764+- @type nodeIdentifier: C{unicode}
765765++ @type nodeIdentifier: L{str}
766766+ @param subscriber: The entity to be subscribed.
767767+ @type subscriber: L{JID<twisted.words.protocols.jabber.jid.JID>}
768768+ @return: A deferred that fires with a
769769+@@ -261,7 +261,7 @@ class IPubSubService(Interface):
770770+ @param service: The entity the request was addressed to.
771771+ @type service: L{JID<twisted.words.protocols.jabber.jid.JID>}
772772+ @param nodeIdentifier: The identifier of the node to unsubscribe from.
773773+- @type nodeIdentifier: C{unicode}
774774++ @type nodeIdentifier: L{str}
775775+ @param subscriber: The entity to be unsubscribed.
776776+ @type subscriber: L{JID<twisted.words.protocols.jabber.jid.JID>}
777777+ @return: A deferred that fires with C{None} when unsubscription has
778778+@@ -277,7 +277,7 @@ class IPubSubService(Interface):
779779+ @type requestor: L{JID<twisted.words.protocols.jabber.jid.JID>}
780780+ @param service: The entity the request was addressed to.
781781+ @type service: L{JID<twisted.words.protocols.jabber.jid.JID>}
782782+- @return: A deferred that fires with a C{list} of subscriptions as
783783++ @return: A deferred that fires with a L{list} of subscriptions as
784784+ L{Subscription<wokkel.pubsub.Subscription>}.
785785+ @rtype: L{Deferred<twisted.internet.defer.Deferred>}
786786+ """
787787+@@ -290,9 +290,9 @@ class IPubSubService(Interface):
788788+ @type requestor: L{JID<twisted.words.protocols.jabber.jid.JID>}
789789+ @param service: The entity the request was addressed to.
790790+ @type service: L{JID<twisted.words.protocols.jabber.jid.JID>}
791791+- @return: A deferred that fires with a C{list} of affiliations as
792792+- C{tuple}s of (node identifier as C{unicode}, affiliation state as
793793+- C{str}). The affiliation can be C{'owner'}, C{'publisher'}, or
794794++ @return: A deferred that fires with a L{list} of affiliations as
795795++ C{tuple}s of (node identifier as L{str}, affiliation state as
796796++ L{str}). The affiliation can be C{'owner'}, C{'publisher'}, or
797797+ C{'outcast'}.
798798+ @rtype: L{Deferred<twisted.internet.defer.Deferred>}
799799+ """
800800+@@ -308,8 +308,8 @@ class IPubSubService(Interface):
801801+ @param nodeIdentifier: The suggestion for the identifier of the node
802802+ to be created. If the request did not include a suggestion for the
803803+ node identifier, the value is C{None}.
804804+- @type nodeIdentifier: C{unicode} or C{NoneType}
805805+- @return: A deferred that fires with a C{unicode} that represents
806806++ @type nodeIdentifier: L{str} or C{NoneType}
807807++ @return: A deferred that fires with a L{str} that represents
808808+ the identifier of the new node.
809809+ @rtype: L{Deferred<twisted.internet.defer.Deferred>}
810810+ """
811811+@@ -322,10 +322,10 @@ class IPubSubService(Interface):
812812+ by option name. The value of each entry represents the specifics for
813813+ that option in a dictionary:
814814+815815+- - C{'type'} (C{str}): The option's type (see
816816++ - C{'type'} (L{str}): The option's type (see
817817+ L{Field<wokkel.data_form.Field>}'s doc string for possible values).
818818+- - C{'label'} (C{unicode}): A human readable label for this option.
819819+- - C{'options'} (C{dict}): Optional list of possible values for this
820820++ - C{'label'} (L{str}): A human readable label for this option.
821821++ - C{'options'} (L{dict}): Optional list of possible values for this
822822+ option.
823823+824824+ Example::
825825+@@ -346,7 +346,7 @@ class IPubSubService(Interface):
826826+ }
827827+ }
828828+829829+- @rtype: C{dict}.
830830++ @rtype: L{dict}.
831831+ """
832832+833833+ def getDefaultConfiguration(requestor, service, nodeType):
834834+@@ -359,11 +359,11 @@ class IPubSubService(Interface):
835835+ @type service: L{JID<twisted.words.protocols.jabber.jid.JID>}
836836+ @param nodeType: The type of node for which the configuration is
837837+ retrieved, C{'leaf'} or C{'collection'}.
838838+- @type nodeType: C{str}
839839+- @return: A deferred that fires with a C{dict} representing the default
840840+- node configuration. Keys are C{str}s that represent the
841841+- field name. Values can be of types C{unicode}, C{int} or
842842+- C{bool}.
843843++ @type nodeType: L{str}
844844++ @return: A deferred that fires with a L{dict} representing the default
845845++ node configuration. Keys are L{str}s that represent the
846846++ field name. Values can be of types L{str}, L{int} or
847847++ L{bool}.
848848+ @rtype: L{Deferred<twisted.internet.defer.Deferred>}
849849+ """
850850+851851+@@ -377,10 +377,10 @@ class IPubSubService(Interface):
852852+ @type service: L{JID<twisted.words.protocols.jabber.jid.JID>}
853853+ @param nodeIdentifier: The identifier of the node to retrieve the
854854+ configuration from.
855855+- @type nodeIdentifier: C{unicode}
856856+- @return: A deferred that fires with a C{dict} representing the node
857857+- configuration. Keys are C{str}s that represent the field name.
858858+- Values can be of types C{unicode}, C{int} or C{bool}.
859859++ @type nodeIdentifier: L{str}
860860++ @return: A deferred that fires with a L{dict} representing the node
861861++ configuration. Keys are L{str}s that represent the field name.
862862++ Values can be of types L{str}, L{int} or L{bool}.
863863+ @rtype: L{Deferred<twisted.internet.defer.Deferred>}
864864+ """
865865+866866+@@ -394,7 +394,7 @@ class IPubSubService(Interface):
867867+ @type service: L{JID<twisted.words.protocols.jabber.jid.JID>}
868868+ @param nodeIdentifier: The identifier of the node to change the
869869+ configuration of.
870870+- @type nodeIdentifier: C{unicode}
871871++ @type nodeIdentifier: L{str}
872872+ @return: A deferred that fires with C{None} when the node's
873873+ configuration has been changed.
874874+ @rtype: L{Deferred<twisted.internet.defer.Deferred>}
875875+@@ -410,7 +410,7 @@ class IPubSubService(Interface):
876876+ @type service: L{JID<twisted.words.protocols.jabber.jid.JID>}
877877+ @param nodeIdentifier: The identifier of the node to retrieve items
878878+ from.
879879+- @type nodeIdentifier: C{unicode}
880880++ @type nodeIdentifier: L{str}
881881+ """
882882+883883+ def retract(requestor, service, nodeIdentifier, itemIdentifiers):
884884+@@ -423,7 +423,7 @@ class IPubSubService(Interface):
885885+ @type service: L{JID<twisted.words.protocols.jabber.jid.JID>}
886886+ @param nodeIdentifier: The identifier of the node to retract items
887887+ from.
888888+- @type nodeIdentifier: C{unicode}
889889++ @type nodeIdentifier: L{str}
890890+ """
891891+892892+ def purge(requestor, service, nodeIdentifier):
893893+@@ -435,7 +435,7 @@ class IPubSubService(Interface):
894894+ @param service: The entity the request was addressed to.
895895+ @type service: L{JID<twisted.words.protocols.jabber.jid.JID>}
896896+ @param nodeIdentifier: The identifier of the node to be purged.
897897+- @type nodeIdentifier: C{unicode}
898898++ @type nodeIdentifier: L{str}
899899+ """
900900+901901+ def delete(requestor, service, nodeIdentifier):
902902+@@ -447,7 +447,7 @@ class IPubSubService(Interface):
903903+ @param service: The entity the request was addressed to.
904904+ @type service: L{JID<twisted.words.protocols.jabber.jid.JID>}
905905+ @param nodeIdentifier: The identifier of the node to be delete.
906906+- @type nodeIdentifier: C{unicode}
907907++ @type nodeIdentifier: L{str}
908908+ """
909909+910910+911911+@@ -472,7 +472,7 @@ class IPubSubResource(Interface):
912912+ @param service: The publish-subscribe service entity.
913913+ @type service: L{JID<twisted.words.protocols.jabber.jid.JID>}
914914+ @param nodeIdentifier: Identifier of the node to request the info for.
915915+- @type nodeIdentifier: C{unicode}
916916++ @type nodeIdentifier: L{str}
917917+ @return: A deferred that fires with a dictionary. If not empty,
918918+ it must have the keys C{'type'} and C{'meta-data'} to keep
919919+ respectively the node type and a dictionary with the meta
920920+@@ -491,7 +491,7 @@ class IPubSubResource(Interface):
921921+ @type service: L{JID<twisted.words.protocols.jabber.jid.JID>}
922922+ @param nodeIdentifier: Identifier of the node to request the childs
923923+ for.
924924+- @type nodeIdentifier: C{unicode}
925925++ @type nodeIdentifier: L{str}
926926+ @return: A deferred that fires with a list of child node identifiers.
927927+ @rtype: L{Deferred<twisted.internet.defer.Deferred>}
928928+ """
929929+@@ -505,10 +505,10 @@ class IPubSubResource(Interface):
930930+ by option name. The value of each entry represents the specifics for
931931+ that option in a dictionary:
932932+933933+- - C{'type'} (C{str}): The option's type (see
934934++ - C{'type'} (L{str}): The option's type (see
935935+ L{Field<wokkel.data_form.Field>}'s doc string for possible values).
936936+- - C{'label'} (C{unicode}): A human readable label for this option.
937937+- - C{'options'} (C{dict}): Optional list of possible values for this
938938++ - C{'label'} (L{str}): A human readable label for this option.
939939++ - C{'options'} (L{dict}): Optional list of possible values for this
940940+ option.
941941+942942+ Example::
943943+@@ -529,7 +529,7 @@ class IPubSubResource(Interface):
944944+ }
945945+ }
946946+947947+- @rtype: C{dict}.
948948++ @rtype: L{dict}.
949949+ """
950950+951951+952952+@@ -574,7 +574,7 @@ class IPubSubResource(Interface):
953953+954954+ @param request: The publish-subscribe request.
955955+ @type request: L{wokkel.pubsub.PubSubRequest}
956956+- @return: A deferred that fires with a C{list} of subscriptions as
957957++ @return: A deferred that fires with a L{list} of subscriptions as
958958+ L{Subscription<wokkel.pubsub.Subscription>}.
959959+ @rtype: L{Deferred<twisted.internet.defer.Deferred>}
960960+ """
961961+@@ -586,9 +586,9 @@ class IPubSubResource(Interface):
962962+963963+ @param request: The publish-subscribe request.
964964+ @type request: L{wokkel.pubsub.PubSubRequest}
965965+- @return: A deferred that fires with a C{list} of affiliations as
966966+- C{tuple}s of (node identifier as C{unicode}, affiliation state as
967967+- C{str}). The affiliation can be C{'owner'}, C{'publisher'}, or
968968++ @return: A deferred that fires with a L{list} of affiliations as
969969++ C{tuple}s of (node identifier as L{str}, affiliation state as
970970++ L{str}). The affiliation can be C{'owner'}, C{'publisher'}, or
971971+ C{'outcast'}.
972972+ @rtype: L{Deferred<twisted.internet.defer.Deferred>}
973973+ """
974974+@@ -600,7 +600,7 @@ class IPubSubResource(Interface):
975975+976976+ @param request: The publish-subscribe request.
977977+ @type request: L{wokkel.pubsub.PubSubRequest}
978978+- @return: A deferred that fires with a C{unicode} that represents
979979++ @return: A deferred that fires with a L{str} that represents
980980+ the identifier of the new node.
981981+ @rtype: L{Deferred<twisted.internet.defer.Deferred>}
982982+ """
983983+@@ -612,10 +612,10 @@ class IPubSubResource(Interface):
984984+985985+ @param request: The publish-subscribe request.
986986+ @type request: L{wokkel.pubsub.PubSubRequest}
987987+- @return: A deferred that fires with a C{dict} representing the default
988988+- node configuration. Keys are C{str}s that represent the
989989+- field name. Values can be of types C{unicode}, C{int} or
990990+- C{bool}.
991991++ @return: A deferred that fires with a L{dict} representing the default
992992++ node configuration. Keys are L{str}s that represent the
993993++ field name. Values can be of types L{str}, L{int} or
994994++ L{bool}.
995995+ @rtype: L{Deferred<twisted.internet.defer.Deferred>}
996996+ """
997997+998998+@@ -626,9 +626,9 @@ class IPubSubResource(Interface):
999999+10001000+ @param request: The publish-subscribe request.
10011001+ @type request: L{wokkel.pubsub.PubSubRequest}
10021002+- @return: A deferred that fires with a C{dict} representing the node
10031003+- configuration. Keys are C{str}s that represent the field name.
10041004+- Values can be of types C{unicode}, C{int} or C{bool}.
10051005++ @return: A deferred that fires with a L{dict} representing the node
10061006++ configuration. Keys are L{str}s that represent the field name.
10071007++ Values can be of types L{str}, L{int} or L{bool}.
10081008+ @rtype: L{Deferred<twisted.internet.defer.Deferred>}
10091009+ """
10101010+10111011+@@ -651,7 +651,7 @@ class IPubSubResource(Interface):
10121012+10131013+ @param request: The publish-subscribe request.
10141014+ @type request: L{wokkel.pubsub.PubSubRequest}
10151015+- @return: A deferred that fires with a C{list} of L{pubsub.Item}.
10161016++ @return: A deferred that fires with a L{list} of L{pubsub.Item}.
10171017+ @rtype: L{Deferred<twisted.internet.defer.Deferred>}
10181018+ """
10191019+10201020+@@ -698,9 +698,9 @@ class IPubSubResource(Interface):
10211021+10221022+ @param request: The publish-subscribe request.
10231023+ @type request: L{wokkel.pubsub.PubSubRequest}
10241024+- @return: A deferred that fires with a C{dict} of affiliations with the
10251025++ @return: A deferred that fires with a L{dict} of affiliations with the
10261026+ entity as key (L{JID<twisted.words.protocols.jabber.jid.JID>}) and
10271027+- the affiliation state as value (C{unicode}). The affiliation can
10281028++ the affiliation state as value (L{str}). The affiliation can
10291029+ be C{u'owner'}, C{u'publisher'}, or C{u'outcast'}.
10301030+ @rtype: L{Deferred<twisted.internet.defer.Deferred>}
10311031+10321032+@@ -748,7 +748,7 @@ class IMUCClient(Interface):
10331033+ @type user: L{muc.User}
10341034+10351035+ @param subject: The subject of the given room.
10361036+- @type subject: C{unicode}
10371037++ @type subject: L{str}
10381038+ """
10391039+10401040+10411041+@@ -769,7 +769,7 @@ class IMUCClient(Interface):
10421042+10431043+ @param options: A mapping of field names to values, or C{None} to
10441044+ cancel.
10451045+- @type options: C{dict}
10461046++ @type options: L{dict}
10471047+ """
10481048+10491049+10501050+@@ -796,14 +796,14 @@ class IMUCClient(Interface):
10511051+ @type roomJID: L{JID<twisted.words.protocols.jabber.jid.JID>}
10521052+10531053+ @param nick: The nick name for the entitity joining the room.
10541054+- @type nick: C{unicode}
10551055++ @type nick: L{str}
10561056+10571057+ @param historyOptions: Options for conversation history sent by the
10581058+ room upon joining.
10591059+ @type historyOptions: L{HistoryOptions}
10601060+10611061+ @param password: Optional password for the room.
10621062+- @type password: C{unicode}
10631063++ @type password: L{str}
10641064+10651065+ @return: A deferred that fires when the entity is in the room or an
10661066+ error has occurred.
10671067+@@ -820,7 +820,7 @@ class IMUCClient(Interface):
10681068+ @type roomJID: L{JID<twisted.words.protocols.jabber.jid.JID>}
10691069+10701070+ @param nick: The new nick name within the room.
10711071+- @type nick: C{unicode}
10721072++ @type nick: L{str}
10731073+ """
10741074+10751075+10761076+@@ -876,7 +876,7 @@ class IMUCClient(Interface):
10771077+10781078+ @param options: A mapping of field names to values, or C{None} to
10791079+ cancel.
10801080+- @type options: C{dict}
10811081++ @type options: L{dict}
10821082+ """
10831083+10841084+10851085+@@ -890,7 +890,7 @@ class IMUCClient(Interface):
10861086+ @type roomJID: L{JID<twisted.words.protocols.jabber.jid.JID>}
10871087+10881088+ @param subject: The subject you want to set.
10891089+- @type subject: C{unicode}
10901090++ @type subject: L{str}
10911091+ """
10921092+10931093+10941094+@@ -917,7 +917,7 @@ class IMUCClient(Interface):
10951095+ holding the original stanza a
10961096+ L{Element<twisted.words.xish.domish.Element>}, and C{'timestamp'}
10971097+ with the timestamp.
10981098+- @type messages: C{list} of
10991099++ @type messages: L{list} of
11001100+ L{Element<twisted.words.xish.domish.Element>}
11011101+ """
11021102+11031103+@@ -933,7 +933,7 @@ class IMUCClient(Interface):
11041104+ @type entity: L{JID<twisted.words.protocols.jabber.jid.JID>}
11051105+11061106+ @param reason: The reason for banning the entity.
11071107+- @type reason: C{unicode}
11081108++ @type reason: L{str}
11091109+11101110+ @param sender: The entity sending the request.
11111111+ @type sender: L{JID<twisted.words.protocols.jabber.jid.JID>}
11121112+@@ -949,10 +949,10 @@ class IMUCClient(Interface):
11131113+11141114+ @param nick: The occupant to be banned.
11151115+ @type nick: L{JID<twisted.words.protocols.jabber.jid.JID>} or
11161116+- C{unicode}
11171117++ L{str}
11181118+11191119+ @param reason: The reason given for the kick.
11201120+- @type reason: C{unicode}
11211121++ @type reason: L{str}
11221122+11231123+ @param sender: The entity sending the request.
11241124+ @type sender: L{JID<twisted.words.protocols.jabber.jid.JID>}
11251125+diff --git a/wokkel/muc.py b/wokkel/muc.py
11261126+index 330664b..4c826f2 100644
11271127+--- a/wokkel/muc.py
11281128++++ b/wokkel/muc.py
11291129+@@ -17,7 +17,6 @@ from dateutil.tz import tzutc
11301130+ from zope.interface import implementer
11311131+11321132+ from twisted.internet import defer
11331133+-from twisted.python.compat import unicode
11341134+ from twisted.python.constants import Values, ValueConstant
11351135+ from twisted.words.protocols.jabber import jid, error, xmlstream
11361136+ from twisted.words.xish import domish
11371137+@@ -192,7 +191,7 @@ class AdminItem(object):
11381138+ item.role = element.getAttribute('role')
11391139+11401140+ for child in element.elements(NS_MUC_ADMIN, 'reason'):
11411141+- item.reason = unicode(child)
11421142++ item.reason = str(child)
11431143+11441144+ return item
11451145+11461146+@@ -228,13 +227,13 @@ class DestructionRequest(generic.Request):
11471147+ Room destruction request.
11481148+11491149+ @param reason: Optional reason for the destruction of this room.
11501150+- @type reason: L{unicode}.
11511151++ @type reason: L{str}.
11521152+11531153+ @param alternate: Optional room JID of an alternate venue.
11541154+ @type alternate: L{JID<twisted.words.protocols.jabber.jid.JID>}
11551155+11561156+ @param password: Optional password for entering the alternate venue.
11571157+- @type password: L{unicode}
11581158++ @type password: L{str}
11591159+ """
11601160+11611161+ stanzaType = 'set'
11621162+@@ -395,10 +394,10 @@ class UserPresence(xmppim.AvailabilityPresence):
11631163+ Availability presence sent from MUC service to client.
11641164+11651165+ @ivar affiliation: Affiliation of the entity to the room.
11661166+- @type affiliation: L{unicode}
11671167++ @type affiliation: L{str}
11681168+11691169+ @ivar role: Role of the entity in the room.
11701170+- @type role: L{unicode}
11711171++ @type role: L{str}
11721172+11731173+ @ivar entity: The real JID of the entity this presence is from.
11741174+ @type entity: L{JID<twisted.words.protocols.jabber.jid.JID>}
11751175+@@ -408,7 +407,7 @@ class UserPresence(xmppim.AvailabilityPresence):
11761176+ @type mucStatuses: L{Statuses}
11771177+11781178+ @ivar nick: The nick name of the entity in the room.
11791179+- @type nick: L{unicode}
11801180++ @type nick: L{str}
11811181+ """
11821182+11831183+ affiliation = None
11841184+@@ -451,7 +450,7 @@ class UserPresence(xmppim.AvailabilityPresence):
11851185+ self.role = child.getAttribute('role')
11861186+11871187+ for reason in child.elements(NS_MUC_ADMIN, 'reason'):
11881188+- self.reason = unicode(reason)
11891189++ self.reason = str(reason)
11901190+11911191+ # TODO: destroy
11921192+11931193+@@ -595,14 +594,14 @@ class MUCClientProtocol(xmppim.BasePresenceProtocol):
11941194+ @type roomJID: L{JID<twisted.words.protocols.jabber.jid.JID>}
11951195+11961196+ @param nick: The nick name for the entitity joining the room.
11971197+- @type nick: L{unicode}
11981198++ @type nick: L{str}
11991199+12001200+ @param historyOptions: Options for conversation history sent by the
12011201+ room upon joining.
12021202+ @type historyOptions: L{HistoryOptions}
12031203+12041204+ @param password: Optional password for the room.
12051205+- @type password: L{unicode}
12061206++ @type password: L{str}
12071207+12081208+ @return: A deferred that fires when the entity is in the room or an
12091209+ error has occurred.
12101210+@@ -628,7 +627,7 @@ class MUCClientProtocol(xmppim.BasePresenceProtocol):
12111211+ @type roomJID: L{JID<twisted.words.protocols.jabber.jid.JID>}
12121212+12131213+ @param nick: The new nick name within the room.
12141214+- @type nick: L{unicode}
12151215++ @type nick: L{str}
12161216+ """
12171217+ occupantJID = jid.JID(tuple=(roomJID.user, roomJID.host, nick))
12181218+ presence = BasicPresence(recipient=occupantJID)
12191219+@@ -646,10 +645,10 @@ class MUCClientProtocol(xmppim.BasePresenceProtocol):
12201220+12211221+ @param show: The availability of the entity. Common values are xa,
12221222+ available, etc
12231223+- @type show: L{unicode}
12241224++ @type show: L{str}
12251225+12261226+ @param status: The current status of the entity.
12271227+- @type status: L{unicode}
12281228++ @type status: L{str}
12291229+ """
12301230+ occupantJID = self._roomOccupantMap[roomJID]
12311231+ presence = BasicPresence(recipient=occupantJID, show=show,
12321232+@@ -704,7 +703,7 @@ class MUCClientProtocol(xmppim.BasePresenceProtocol):
12331233+ @type roomJID: L{JID<twisted.words.protocols.jabber.jid.JID>}
12341234+12351235+ @param subject: The subject you want to set.
12361236+- @type subject: L{unicode}
12371237++ @type subject: L{str}
12381238+ """
12391239+ message = GroupChat(roomJID.userhostJID(), subject=subject)
12401240+ self.send(message.toElement())
12411241+@@ -723,7 +722,7 @@ class MUCClientProtocol(xmppim.BasePresenceProtocol):
12421242+ @type invitee: L{JID<twisted.words.protocols.jabber.jid.JID>}
12431243+12441244+ @param reason: The reason for the invite.
12451245+- @type reason: L{unicode}
12461246++ @type reason: L{str}
12471247+ """
12481248+ message = InviteMessage(recipient=roomJID, invitee=invitee,
12491249+ reason=reason)
12501250+@@ -970,7 +969,7 @@ class MUCClientProtocol(xmppim.BasePresenceProtocol):
12511251+ L{JID<twisted.words.protocols.jabber.jid.JID>}
12521252+12531253+ @param affiliation: The affilation to the entities will acquire.
12541254+- @type affiliation: L{unicode}
12551255++ @type affiliation: L{str}
12561256+12571257+ @param sender: The entity sending the request.
12581258+ @type sender: L{JID<twisted.words.protocols.jabber.jid.JID>}
12591259+@@ -992,10 +991,10 @@ class MUCClientProtocol(xmppim.BasePresenceProtocol):
12601260+ @type roomJID: L{JID<twisted.words.protocols.jabber.jid.JID>}
12611261+12621262+ @param nick: The nick name for the user in this room.
12631263+- @type nick: L{unicode}
12641264++ @type nick: L{str}
12651265+12661266+ @param reason: The reason for granting voice to the entity.
12671267+- @type reason: L{unicode}
12681268++ @type reason: L{str}
12691269+12701270+ @param sender: The entity sending the request.
12711271+ @type sender: L{JID<twisted.words.protocols.jabber.jid.JID>}
12721272+@@ -1015,10 +1014,10 @@ class MUCClientProtocol(xmppim.BasePresenceProtocol):
12731273+ @type roomJID: L{JID<twisted.words.protocols.jabber.jid.JID>}
12741274+12751275+ @param nick: The nick name for the user in this room.
12761276+- @type nick: L{unicode}
12771277++ @type nick: L{str}
12781278+12791279+ @param reason: The reason for revoking voice from the entity.
12801280+- @type reason: L{unicode}
12811281++ @type reason: L{str}
12821282+12831283+ @param sender: The entity sending the request.
12841284+ @type sender: L{JID<twisted.words.protocols.jabber.jid.JID>}
12851285+@@ -1035,10 +1034,10 @@ class MUCClientProtocol(xmppim.BasePresenceProtocol):
12861286+ @type roomJID: L{JID<twisted.words.protocols.jabber.jid.JID>}
12871287+12881288+ @param nick: The nick name for the user in this room.
12891289+- @type nick: L{unicode}
12901290++ @type nick: L{str}
12911291+12921292+ @param reason: The reason for granting moderation to the entity.
12931293+- @type reason: L{unicode}
12941294++ @type reason: L{str}
12951295+12961296+ @param sender: The entity sending the request.
12971297+ @type sender: L{JID<twisted.words.protocols.jabber.jid.JID>}
12981298+@@ -1058,7 +1057,7 @@ class MUCClientProtocol(xmppim.BasePresenceProtocol):
12991299+ @type entity: L{JID<twisted.words.protocols.jabber.jid.JID>}
13001300+13011301+ @param reason: The reason for banning the entity.
13021302+- @type reason: L{unicode}
13031303++ @type reason: L{str}
13041304+13051305+ @param sender: The entity sending the request.
13061306+ @type sender: L{JID<twisted.words.protocols.jabber.jid.JID>}
13071307+@@ -1075,10 +1074,10 @@ class MUCClientProtocol(xmppim.BasePresenceProtocol):
13081308+ @type roomJID: L{JID<twisted.words.protocols.jabber.jid.JID>}
13091309+13101310+ @param nick: The occupant to be banned.
13111311+- @type nick: L{unicode}
13121312++ @type nick: L{str}
13131313+13141314+ @param reason: The reason given for the kick.
13151315+- @type reason: L{unicode}
13161316++ @type reason: L{str}
13171317+13181318+ @param sender: The entity sending the request.
13191319+ @type sender: L{JID<twisted.words.protocols.jabber.jid.JID>}
13201320+@@ -1095,7 +1094,7 @@ class MUCClientProtocol(xmppim.BasePresenceProtocol):
13211321+ @type roomJID: L{JID<twisted.words.protocols.jabber.jid.JID>}
13221322+13231323+ @param reason: The reason for the destruction of the room.
13241324+- @type reason: L{unicode}
13251325++ @type reason: L{str}
13261326+13271327+ @param alternate: The JID of the room suggested as an alternate venue.
13281328+ @type alternate: L{JID<twisted.words.protocols.jabber.jid.JID>}
13291329+@@ -1135,7 +1134,7 @@ class Room(object):
13301330+ @type roomJID: L{JID<twisted.words.protocols.jabber.jid.JID>}
13311331+13321332+ @ivar nick: The nick name for the client in this room.
13331333+- @type nick: L{unicode}
13341334++ @type nick: L{str}
13351335+13361336+ @ivar occupantJID: The JID of the occupant in the room. Generated from
13371337+ roomJID and nick.
13381338+@@ -1190,7 +1189,7 @@ class Room(object):
13391339+ Get a user from the room's roster.
13401340+13411341+ @param nick: The nick for the user in the MUC room.
13421342+- @type nick: L{unicode}
13431343++ @type nick: L{str}
13441344+ """
13451345+ return self.roster.get(nick)
13461346+13471347+@@ -1444,14 +1443,14 @@ class MUCClient(MUCClientProtocol):
13481348+ @type roomJID: L{JID<twisted.words.protocols.jabber.jid.JID>}
13491349+13501350+ @param nick: The nick name for the entitity joining the room.
13511351+- @type nick: L{unicode}
13521352++ @type nick: L{str}
13531353+13541354+ @param historyOptions: Options for conversation history sent by the
13551355+ room upon joining.
13561356+ @type historyOptions: L{HistoryOptions}
13571357+13581358+ @param password: Optional password for the room.
13591359+- @type password: L{unicode}
13601360++ @type password: L{str}
13611361+13621362+ @return: A deferred that fires with the room when the entity is in the
13631363+ room, or with a failure if an error has occurred.
13641364+@@ -1488,7 +1487,7 @@ class MUCClient(MUCClientProtocol):
13651365+ @type roomJID: L{JID<twisted.words.protocols.jabber.jid.JID>}
13661366+13671367+ @param nick: The new nick name within the room.
13681368+- @type nick: L{unicode}
13691369++ @type nick: L{str}
13701370+ """
13711371+ def cb(presence):
13721372+ # Presence confirmation, change the nickname.
13731373+@@ -1530,10 +1529,10 @@ class MUCClient(MUCClientProtocol):
13741374+13751375+ @param show: The availability of the entity. Common values are xa,
13761376+ available, etc
13771377+- @type show: L{unicode}
13781378++ @type show: L{str}
13791379+13801380+ @param status: The current status of the entity.
13811381+- @type status: L{unicode}
13821382++ @type status: L{str}
13831383+ """
13841384+ room = self._getRoom(roomJID)
13851385+ d = MUCClientProtocol.status(self, roomJID, show, status)
13861386+@@ -1549,7 +1548,7 @@ class MUCClient(MUCClientProtocol):
13871387+ @type roomJID: L{JID<twisted.words.protocols.jabber.jid.JID>}
13881388+13891389+ @param reason: The reason for the destruction of the room.
13901390+- @type reason: L{unicode}
13911391++ @type reason: L{str}
13921392+13931393+ @param alternate: The JID of the room suggested as an alternate venue.
13941394+ @type alternate: L{JID<twisted.words.protocols.jabber.jid.JID>}
13951395+diff --git a/wokkel/pubsub.py b/wokkel/pubsub.py
13961396+index 689a6e2..2eb1b44 100644
13971397+--- a/wokkel/pubsub.py
13981398++++ b/wokkel/pubsub.py
13991399+@@ -16,7 +16,6 @@ from zope.interface import implementer
14001400+14011401+ from twisted.internet import defer
14021402+ from twisted.python import log
14031403+-from twisted.python.compat import StringType, iteritems, unicode
14041404+ from twisted.words.protocols.jabber import jid, error
14051405+ from twisted.words.xish import domish
14061406+14071407+@@ -107,20 +106,20 @@ class Subscription(object):
14081408+14091409+ @ivar nodeIdentifier: The identifier of the node subscribed to. The root
14101410+ node is denoted by L{None}.
14111411+- @type nodeIdentifier: L{unicode}
14121412++ @type nodeIdentifier: L{str}
14131413+14141414+ @ivar subscriber: The subscribing entity.
14151415+ @type subscriber: L{jid.JID}
14161416+14171417+ @ivar state: The subscription state. One of C{'subscribed'}, C{'pending'},
14181418+ C{'unconfigured'}.
14191419+- @type state: L{unicode}
14201420++ @type state: L{str}
14211421+14221422+ @ivar options: Optional list of subscription options.
14231423+ @type options: L{dict}
14241424+14251425+ @ivar subscriptionIdentifier: Optional subscription identifier.
14261426+- @type subscriptionIdentifier: L{unicode}
14271427++ @type subscriptionIdentifier: L{str}
14281428+ """
14291429+14301430+ def __init__(self, nodeIdentifier, subscriber, state, options=None,
14311431+@@ -150,7 +149,7 @@ class Subscription(object):
14321432+ element = domish.Element((defaultUri, 'subscription'))
14331433+ if self.nodeIdentifier:
14341434+ element['node'] = self.nodeIdentifier
14351435+- element['jid'] = unicode(self.subscriber)
14361436++ element['jid'] = str(self.subscriber)
14371437+ element['subscription'] = self.state
14381438+ if self.subscriptionIdentifier:
14391439+ element['subid'] = self.subscriptionIdentifier
14401440+@@ -171,17 +170,17 @@ class Item(domish.Element):
14411441+ def __init__(self, id=None, payload=None):
14421442+ """
14431443+ @param id: optional item identifier
14441444+- @type id: L{unicode}
14451445++ @type id: L{str}
14461446+ @param payload: optional item payload. Either as a domish element, or
14471447+ as serialized XML.
14481448+- @type payload: object providing L{domish.IElement} or L{unicode}.
14491449++ @type payload: object providing L{domish.IElement} or L{str}.
14501450+ """
14511451+14521452+ domish.Element.__init__(self, (None, 'item'))
14531453+ if id is not None:
14541454+ self['id'] = id
14551455+ if payload is not None:
14561456+- if isinstance(payload, StringType):
14571457++ if isinstance(payload, str):
14581458+ self.addRawXml(payload)
14591459+ else:
14601460+ self.addChild(payload)
14611461+@@ -213,7 +212,7 @@ class PubSubRequest(generic.Stanza):
14621462+ @type maxItems: L{int}.
14631463+14641464+ @ivar nodeIdentifier: Identifier of the node the request is about.
14651465+- @type nodeIdentifier: L{unicode}
14661466++ @type nodeIdentifier: L{str}
14671467+14681468+ @ivar nodeType: The type of node that should be created, or for which the
14691469+ configuration is retrieved. C{'leaf'} or C{'collection'}.
14701470+@@ -227,7 +226,7 @@ class PubSubRequest(generic.Stanza):
14711471+ @type subscriber: L{JID<twisted.words.protocols.jabber.jid.JID>}
14721472+14731473+ @ivar subscriptionIdentifier: Identifier for a specific subscription.
14741474+- @type subscriptionIdentifier: L{unicode}
14751475++ @type subscriptionIdentifier: L{str}
14761476+14771477+ @ivar subscriptions: Subscriptions to be modified, as a set of
14781478+ L{Subscription}.
14791479+@@ -235,7 +234,7 @@ class PubSubRequest(generic.Stanza):
14801480+14811481+ @ivar affiliations: Affiliations to be modified, as a dictionary of entity
14821482+ (L{JID<twisted.words.protocols.jabber.jid.JID>} to affiliation
14831483+- (L{unicode}).
14841484++ (L{str}).
14851485+ @type affiliations: L{dict}
14861486+ """
14871487+14881488+@@ -277,7 +276,7 @@ class PubSubRequest(generic.Stanza):
14891489+ }
14901490+14911491+ # Map request verb to request iq type and subelement name
14921492+- _verbRequestMap = dict(((v, k) for k, v in iteritems(_requestVerbMap)))
14931493++ _verbRequestMap = dict(((v, k) for k, v in _requestVerbMap.items()))
14941494+14951495+ # Map request verb to parameter handler names
14961496+ _parameters = {
14971497+@@ -487,7 +486,7 @@ class PubSubRequest(generic.Stanza):
14981498+ Render maximum items into an items request.
14991499+ """
15001500+ if self.maxItems:
15011501+- verbElement['max_items'] = unicode(self.maxItems)
15021502++ verbElement['max_items'] = str(self.maxItems)
15031503+15041504+15051505+ def _parse_subidOrNone(self, verbElement):
15061506+@@ -648,7 +647,7 @@ class PubSubEvent(object):
15071507+ @param recipient: The entity to which the notification was sent.
15081508+ @type recipient: L{wokkel.pubsub.ItemsEvent}
15091509+ @param nodeIdentifier: Identifier of the node the event pertains to.
15101510+- @type nodeIdentifier: L{unicode}
15111511++ @type nodeIdentifier: L{str}
15121512+ @param headers: SHIM headers, see L{wokkel.shim.extractHeaders}.
15131513+ @type headers: L{dict}
15141514+ """
15151515+@@ -772,7 +771,7 @@ class PubSubClient(XMPPHandler):
15161516+ @param service: The publish subscribe service to create the node at.
15171517+ @type service: L{JID<twisted.words.protocols.jabber.jid.JID>}
15181518+ @param nodeIdentifier: Optional suggestion for the id of the node.
15191519+- @type nodeIdentifier: L{unicode}
15201520++ @type nodeIdentifier: L{str}
15211521+ @param options: Optional node configuration options.
15221522+ @type options: L{dict}
15231523+ """
15241524+@@ -807,7 +806,7 @@ class PubSubClient(XMPPHandler):
15251525+ @param service: The publish subscribe service to delete the node from.
15261526+ @type service: L{JID<twisted.words.protocols.jabber.jid.JID>}
15271527+ @param nodeIdentifier: The identifier of the node.
15281528+- @type nodeIdentifier: L{unicode}
15291529++ @type nodeIdentifier: L{str}
15301530+ """
15311531+ request = PubSubRequest('delete')
15321532+ request.recipient = service
15331533+@@ -825,7 +824,7 @@ class PubSubClient(XMPPHandler):
15341534+ @type service: L{JID<twisted.words.protocols.jabber.jid.JID>}
15351535+15361536+ @param nodeIdentifier: The identifier of the node.
15371537+- @type nodeIdentifier: L{unicode}
15381538++ @type nodeIdentifier: L{str}
15391539+15401540+ @param subscriber: The entity to subscribe to the node. This entity
15411541+ will get notifications of new published items.
15421542+@@ -877,13 +876,13 @@ class PubSubClient(XMPPHandler):
15431543+ @type service: L{JID<twisted.words.protocols.jabber.jid.JID>}
15441544+15451545+ @param nodeIdentifier: The identifier of the node.
15461546+- @type nodeIdentifier: L{unicode}
15471547++ @type nodeIdentifier: L{str}
15481548+15491549+ @param subscriber: The entity to unsubscribe from the node.
15501550+ @type subscriber: L{JID<twisted.words.protocols.jabber.jid.JID>}
15511551+15521552+ @param subscriptionIdentifier: Optional subscription identifier.
15531553+- @type subscriptionIdentifier: L{unicode}
15541554++ @type subscriptionIdentifier: L{str}
15551555+ """
15561556+ request = PubSubRequest('unsubscribe')
15571557+ request.recipient = service
15581558+@@ -901,7 +900,7 @@ class PubSubClient(XMPPHandler):
15591559+ @param service: The publish subscribe service that keeps the node.
15601560+ @type service: L{JID<twisted.words.protocols.jabber.jid.JID>}
15611561+ @param nodeIdentifier: The identifier of the node.
15621562+- @type nodeIdentifier: L{unicode}
15631563++ @type nodeIdentifier: L{str}
15641564+ @param items: Optional list of L{Item}s to publish.
15651565+ @type items: L{list}
15661566+ """
15671567+@@ -922,7 +921,7 @@ class PubSubClient(XMPPHandler):
15681568+ @type service: L{JID<twisted.words.protocols.jabber.jid.JID>}
15691569+15701570+ @param nodeIdentifier: The identifier of the node.
15711571+- @type nodeIdentifier: L{unicode}
15721572++ @type nodeIdentifier: L{str}
15731573+15741574+ @param maxItems: Optional limit on the number of retrieved items.
15751575+ @type maxItems: L{int}
15761576+@@ -930,10 +929,10 @@ class PubSubClient(XMPPHandler):
15771577+ @param subscriptionIdentifier: Optional subscription identifier. In
15781578+ case the node has been subscribed to multiple times, this narrows
15791579+ the results to the specific subscription.
15801580+- @type subscriptionIdentifier: L{unicode}
15811581++ @type subscriptionIdentifier: L{str}
15821582+15831583+ @param itemIdentifiers: Identifiers of the items to be retrieved.
15841584+- @type itemIdentifiers: L{set} of L{unicode}
15851585++ @type itemIdentifiers: L{set} of L{str}
15861586+ """
15871587+ request = PubSubRequest('items')
15881588+ request.recipient = service
15891589+@@ -965,13 +964,13 @@ class PubSubClient(XMPPHandler):
15901590+ @type service: L{JID<twisted.words.protocols.jabber.jid.JID>}
15911591+15921592+ @param nodeIdentifier: The identifier of the node.
15931593+- @type nodeIdentifier: L{unicode}
15941594++ @type nodeIdentifier: L{str}
15951595+15961596+ @param subscriber: The entity subscribed to the node.
15971597+ @type subscriber: L{JID<twisted.words.protocols.jabber.jid.JID>}
15981598+15991599+ @param subscriptionIdentifier: Optional subscription identifier.
16001600+- @type subscriptionIdentifier: L{unicode}
16011601++ @type subscriptionIdentifier: L{str}
16021602+16031603+ @rtype: L{data_form.Form}
16041604+ """
16051605+@@ -1002,7 +1001,7 @@ class PubSubClient(XMPPHandler):
16061606+ @type service: L{JID<twisted.words.protocols.jabber.jid.JID>}
16071607+16081608+ @param nodeIdentifier: The identifier of the node.
16091609+- @type nodeIdentifier: L{unicode}
16101610++ @type nodeIdentifier: L{str}
16111611+16121612+ @param subscriber: The entity subscribed to the node.
16131613+ @type subscriber: L{JID<twisted.words.protocols.jabber.jid.JID>}
16141614+@@ -1011,7 +1010,7 @@ class PubSubClient(XMPPHandler):
16151615+ @type options: L{dict}.
16161616+16171617+ @param subscriptionIdentifier: Optional subscription identifier.
16181618+- @type subscriptionIdentifier: L{unicode}
16191619++ @type subscriptionIdentifier: L{str}
16201620+ """
16211621+ request = PubSubRequest('optionsSet')
16221622+ request.recipient = service
16231623+@@ -1356,7 +1355,7 @@ class PubSubService(XMPPHandler, IQHandlerMixin):
16241624+ if request.nodeIdentifier:
16251625+ affiliations['node'] = request.nodeIdentifier
16261626+16271627+- for entity, affiliation in iteritems(result):
16281628++ for entity, affiliation in result.items():
16291629+ item = affiliations.addElement('affiliation')
16301630+ item['jid'] = entity.full()
16311631+ item['affiliation'] = affiliation
16321632+diff --git a/wokkel/server.py b/wokkel/server.py
16331633+index 54517a2..fbd8452 100644
16341634+--- a/wokkel/server.py
16351635++++ b/wokkel/server.py
16361636+@@ -22,7 +22,6 @@ from zope.interface import implementer
16371637+ from twisted.internet import defer, reactor
16381638+ from twisted.names.srvconnect import SRVConnector
16391639+ from twisted.python import log, randbytes
16401640+-from twisted.python.compat import iteritems, unicode
16411641+ from twisted.words.protocols.jabber import error, ijabber, jid, xmlstream
16421642+ from twisted.words.xish import domish
16431643+16441644+@@ -40,15 +39,15 @@ def generateKey(secret, receivingServer, originatingServer, streamID):
16451645+16461646+ @param secret: the shared secret known to the Originating Server and
16471647+ Authoritive Server.
16481648+- @type secret: L{unicode}
16491649++ @type secret: L{str}
16501650+ @param receivingServer: the Receiving Server host name.
16511651+- @type receivingServer: L{unicode}
16521652++ @type receivingServer: L{str}
16531653+ @param originatingServer: the Originating Server host name.
16541654+- @type originatingServer: L{unicode}
16551655++ @type originatingServer: L{str}
16561656+ @param streamID: the Stream ID as generated by the Receiving Server.
16571657+- @type streamID: L{unicode}
16581658++ @type streamID: L{str}
16591659+ @return: hexadecimal digest of the generated key.
16601660+- @type: C{str}
16611661++ @type: L{str}
16621662+ """
16631663+16641664+ hashObject = sha256()
16651665+@@ -340,7 +339,7 @@ class XMPPServerListenAuthenticator(xmlstream.ListenAuthenticator):
16661666+ try:
16671667+ if xmlstream.NS_STREAMS != rootElement.uri or \
16681668+ self.namespace != self.xmlstream.namespace or \
16691669+- ('db', NS_DIALBACK) not in iteritems(rootElement.localPrefixes):
16701670++ ('db', NS_DIALBACK) not in rootElement.localPrefixes.items():
16711671+ raise error.StreamError('invalid-namespace')
16721672+16731673+ if targetDomain and targetDomain not in self.service.domains:
16741674+@@ -379,7 +378,7 @@ class XMPPServerListenAuthenticator(xmlstream.ListenAuthenticator):
16751675+ raise error.StreamError('invalid-from')
16761676+16771677+ streamID = verify.getAttribute('id', '')
16781678+- key = unicode(verify)
16791679++ key = str(verify)
16801680+16811681+ calculatedKey = generateKey(self.service.secret, receivingServer,
16821682+ originatingServer, streamID)
16831683+@@ -415,7 +414,7 @@ class XMPPServerListenAuthenticator(xmlstream.ListenAuthenticator):
16841684+16851685+ receivingServer = result['to']
16861686+ originatingServer = result['from']
16871687+- key = unicode(result)
16881688++ key = str(result)
16891689+16901690+ d = self.service.validateConnection(receivingServer, originatingServer,
16911691+ self.xmlstream.sid, key)
16921692+diff --git a/wokkel/shim.py b/wokkel/shim.py
16931693+index 3b12349..85a0848 100644
16941694+--- a/wokkel/shim.py
16951695++++ b/wokkel/shim.py
16961696+@@ -12,7 +12,6 @@ U{XEP-0131<http://xmpp.org/extensions/xep-0131.html>}.
16971697+16981698+ from __future__ import division, absolute_import
16991699+17001700+-from twisted.python.compat import unicode
17011701+ from twisted.words.xish import domish
17021702+17031703+ NS_SHIM = "http://jabber.org/protocol/shim"
17041704+@@ -30,7 +29,7 @@ def extractHeaders(stanza):
17051705+ @param stanza: The stanza to extract headers from.
17061706+ @type stanza: L{Element<twisted.words.xish.domish.Element>}
17071707+ @return: Headers as a mapping from header name to a list of values.
17081708+- @rtype: C{dict}
17091709++ @rtype: L{dict}
17101710+ """
17111711+ headers = {}
17121712+17131713+@@ -38,6 +37,6 @@ def extractHeaders(stanza):
17141714+ 'headers', NS_SHIM):
17151715+ for header in domish.generateElementsQNamed(element.children,
17161716+ 'header', NS_SHIM):
17171717+- headers.setdefault(header['name'], []).append(unicode(header))
17181718++ headers.setdefault(header['name'], []).append(str(header))
17191719+17201720+ return headers
17211721+diff --git a/wokkel/subprotocols.py b/wokkel/subprotocols.py
17221722+index f0a6090..b4cde14 100644
17231723+--- a/wokkel/subprotocols.py
17241724++++ b/wokkel/subprotocols.py
17251725+@@ -14,7 +14,6 @@ from zope.interface import implementer
17261726+ from twisted.internet import defer
17271727+ from twisted.internet.error import ConnectionDone
17281728+ from twisted.python import failure, log
17291729+-from twisted.python.compat import iteritems, itervalues
17301730+ from twisted.python.deprecate import deprecatedModuleAttribute
17311731+ from twisted.words.protocols.jabber import error, ijabber, xmlstream
17321732+ from twisted.words.protocols.jabber.xmlstream import toResponse
17331733+@@ -130,15 +129,15 @@ class StreamManager(XMPPHandlerCollection):
17341734+ @ivar xmlstream: currently managed XML stream
17351735+ @type xmlstream: L{XmlStream}
17361736+ @ivar logTraffic: if true, log all traffic.
17371737+- @type logTraffic: C{bool}
17381738++ @type logTraffic: L{bool}
17391739+ @ivar _initialized: Whether the stream represented by L{xmlstream} has
17401740+ been initialized. This is used when caching outgoing
17411741+ stanzas.
17421742+- @type _initialized: C{bool}
17431743++ @type _initialized: L{bool}
17441744+ @ivar _packetQueue: internal buffer of unsent data. See L{send} for details.
17451745+ @type _packetQueue: L{list}
17461746+ @ivar timeout: Default IQ request timeout in seconds.
17471747+- @type timeout: C{int}
17481748++ @type timeout: L{int}
17491749+ @ivar _reactor: A provider of L{IReactorTime} to track timeouts.
17501750+ """
17511751+ timeout = None
17521752+@@ -277,7 +276,7 @@ class StreamManager(XMPPHandlerCollection):
17531753+ # deferreds will never be fired.
17541754+ iqDeferreds = self._iqDeferreds
17551755+ self._iqDeferreds = {}
17561756+- for d in itervalues(iqDeferreds):
17571757++ for d in iqDeferreds.values():
17581758+ d.errback(reason)
17591759+17601760+17611761+@@ -420,7 +419,7 @@ class IQHandlerMixin(object):
17621762+17631763+ @cvar iqHandlers: Mapping from XPath queries (as a string) to the method
17641764+ name that will handle requests that match the query.
17651765+- @type iqHandlers: C{dict}
17661766++ @type iqHandlers: L{dict}
17671767+ """
17681768+17691769+ iqHandlers = None
17701770+@@ -455,7 +454,7 @@ class IQHandlerMixin(object):
17711771+ return error.StanzaError('internal-server-error').toResponse(iq)
17721772+17731773+ handler = None
17741774+- for queryString, method in iteritems(self.iqHandlers):
17751775++ for queryString, method in self.iqHandlers.items():
17761776+ if xpath.internQuery(queryString).matches(iq):
17771777+ handler = getattr(self, method)
17781778+17791779+diff --git a/wokkel/test/helpers.py b/wokkel/test/helpers.py
17801780+index 102b3dc..c76a4a0 100644
17811781+--- a/wokkel/test/helpers.py
17821782++++ b/wokkel/test/helpers.py
17831783+@@ -8,7 +8,6 @@ Unit test helpers.
17841784+ from __future__ import division, absolute_import
17851785+17861786+ from twisted.internet import defer
17871787+-from twisted.python.compat import iteritems
17881788+ from twisted.words.xish import xpath
17891789+ from twisted.words.xish.utility import EventDispatcher
17901790+17911791+@@ -79,14 +78,14 @@ class TestableRequestHandlerMixin(object):
17921792+ Find a handler and call it directly.
17931793+17941794+ @param xml: XML stanza that may yield a handler being called.
17951795+- @type xml: C{str}.
17961796++ @type xml: L{str}.
17971797+ @return: Deferred that fires with the result of a handler for this
17981798+ stanza. If no handler was found, the deferred has its errback
17991799+ called with a C{NotImplementedError} exception.
18001800+ """
18011801+ handler = None
18021802+ iq = parseXml(xml)
18031803+- for queryString, method in iteritems(self.service.iqHandlers):
18041804++ for queryString, method in self.service.iqHandlers.items():
18051805+ if xpath.internQuery(queryString).matches(iq):
18061806+ handler = getattr(self.service, method)
18071807+18081808+diff --git a/wokkel/test/test_client.py b/wokkel/test/test_client.py
18091809+index ef367f7..ef9adfd 100644
18101810+--- a/wokkel/test/test_client.py
18111811++++ b/wokkel/test/test_client.py
18121812+@@ -8,6 +8,7 @@ Tests for L{wokkel.client}.
18131813+ from __future__ import division, absolute_import
18141814+18151815+ from twisted.internet import defer
18161816++from twisted.python.compat import nativeString
18171817+ from twisted.trial import unittest
18181818+ from twisted.words.protocols.jabber import xmlstream
18191819+ from twisted.words.protocols.jabber.client import XMPPAuthenticator
18201820+@@ -152,7 +153,7 @@ class ClientCreatorTest(unittest.TestCase):
18211821+18221822+ def cb(connector):
18231823+ self.assertEqual('xmpp-client', connector.service)
18241824+- self.assertEqual('example.org', connector.domain)
18251825++ self.assertEqual('example.org', nativeString(connector.domain))
18261826+ self.assertEqual(factory, connector.factory)
18271827+18281828+ def connect(connector):
18291829+diff --git a/wokkel/test/test_data_form.py b/wokkel/test/test_data_form.py
18301830+index 60e36f4..246f1c5 100644
18311831+--- a/wokkel/test/test_data_form.py
18321832++++ b/wokkel/test/test_data_form.py
18331833+@@ -10,7 +10,6 @@ from __future__ import division, absolute_import
18341834+ from zope.interface import verify
18351835+ from zope.interface.common.mapping import IIterableMapping
18361836+18371837+-from twisted.python.compat import unicode, _PY3
18381838+ from twisted.trial import unittest
18391839+ from twisted.words.xish import domish
18401840+ from twisted.words.protocols.jabber import jid
18411841+@@ -34,7 +33,7 @@ class OptionTest(unittest.TestCase):
18421842+ self.assertEqual('option', element.name)
18431843+ self.assertEqual(NS_X_DATA, element.uri)
18441844+ self.assertEqual(NS_X_DATA, element.value.uri)
18451845+- self.assertEqual('value', unicode(element.value))
18461846++ self.assertEqual('value', str(element.value))
18471847+ self.assertFalse(element.hasAttribute('label'))
18481848+18491849+18501850+@@ -48,7 +47,7 @@ class OptionTest(unittest.TestCase):
18511851+ self.assertEqual('option', element.name)
18521852+ self.assertEqual(NS_X_DATA, element.uri)
18531853+ self.assertEqual(NS_X_DATA, element.value.uri)
18541854+- self.assertEqual('value', unicode(element.value))
18551855++ self.assertEqual('value', str(element.value))
18561856+ self.assertEqual('label', element['label'])
18571857+18581858+18591859+@@ -225,7 +224,7 @@ class FieldTest(unittest.TestCase):
18601860+ child = element.children[0]
18611861+ self.assertEqual('desc', child.name)
18621862+ self.assertEqual(NS_X_DATA, child.uri)
18631863+- self.assertEqual(u'My desc', unicode(child))
18641864++ self.assertEqual(u'My desc', str(child))
18651865+18661866+18671867+ def test_toElementRequired(self):
18681868+@@ -248,7 +247,7 @@ class FieldTest(unittest.TestCase):
18691869+ field = data_form.Field(fieldType='jid-single', var='test',
18701870+ value=jid.JID(u'test@example.org'))
18711871+ element = field.toElement()
18721872+- self.assertEqual(u'test@example.org', unicode(element.value))
18731873++ self.assertEqual(u'test@example.org', str(element.value))
18741874+18751875+18761876+ def test_toElementJIDTextSingle(self):
18771877+@@ -258,7 +257,7 @@ class FieldTest(unittest.TestCase):
18781878+ field = data_form.Field(fieldType='text-single', var='test',
18791879+ value=jid.JID(u'test@example.org'))
18801880+ element = field.toElement()
18811881+- self.assertEqual(u'test@example.org', unicode(element.value))
18821882++ self.assertEqual(u'test@example.org', str(element.value))
18831883+18841884+18851885+ def test_toElementBoolean(self):
18861886+@@ -268,7 +267,7 @@ class FieldTest(unittest.TestCase):
18871887+ field = data_form.Field(fieldType='boolean', var='test',
18881888+ value=True)
18891889+ element = field.toElement()
18901890+- self.assertEqual(u'true', unicode(element.value))
18911891++ self.assertEqual(u'true', str(element.value))
18921892+18931893+18941894+ def test_toElementBooleanTextSingle(self):
18951895+@@ -277,7 +276,7 @@ class FieldTest(unittest.TestCase):
18961896+ """
18971897+ field = data_form.Field(var='test', value=True)
18981898+ element = field.toElement()
18991899+- self.assertEqual(u'true', unicode(element.value))
19001900++ self.assertEqual(u'true', str(element.value))
19011901+19021902+19031903+ def test_toElementNoType(self):
19041904+@@ -396,7 +395,7 @@ class FieldTest(unittest.TestCase):
19051905+19061906+ def test_fromElementValueTextSingle(self):
19071907+ """
19081908+- Parsed text-single field values should be of type C{unicode}.
19091909++ Parsed text-single field values should be of type L{str}.
19101910+ """
19111911+ element = domish.Element((NS_X_DATA, 'field'))
19121912+ element['type'] = 'text-single'
19131913+@@ -407,7 +406,7 @@ class FieldTest(unittest.TestCase):
19141914+19151915+ def test_fromElementValueJID(self):
19161916+ """
19171917+- Parsed jid-single field values should be of type C{unicode}.
19181918++ Parsed jid-single field values should be of type L{str}.
19191919+ """
19201920+ element = domish.Element((NS_X_DATA, 'field'))
19211921+ element['type'] = 'jid-single'
19221922+@@ -418,7 +417,7 @@ class FieldTest(unittest.TestCase):
19231923+19241924+ def test_fromElementValueJIDMalformed(self):
19251925+ """
19261926+- Parsed jid-single field values should be of type C{unicode}.
19271927++ Parsed jid-single field values should be of type L{str}.
19281928+19291929+ No validation should be done at this point, so invalid JIDs should
19301930+ also be passed as-is.
19311931+@@ -432,7 +431,7 @@ class FieldTest(unittest.TestCase):
19321932+19331933+ def test_fromElementValueBoolean(self):
19341934+ """
19351935+- Parsed boolean field values should be of type C{unicode}.
19361936++ Parsed boolean field values should be of type L{str}.
19371937+ """
19381938+ element = domish.Element((NS_X_DATA, 'field'))
19391939+ element['type'] = 'boolean'
19401940+@@ -561,7 +560,7 @@ class FormTest(unittest.TestCase):
19411941+ title = elements[0]
19421942+ self.assertEqual('title', title.name)
19431943+ self.assertEqual(NS_X_DATA, title.uri)
19441944+- self.assertEqual('Bot configuration', unicode(title))
19451945++ self.assertEqual('Bot configuration', str(title))
19461946+19471947+19481948+ def test_toElementInstructions(self):
19491949+@@ -576,7 +575,7 @@ class FormTest(unittest.TestCase):
19501950+ instructions = elements[0]
19511951+ self.assertEqual('instructions', instructions.name)
19521952+ self.assertEqual(NS_X_DATA, instructions.uri)
19531953+- self.assertEqual('Fill out this form!', unicode(instructions))
19541954++ self.assertEqual('Fill out this form!', str(instructions))
19551955+19561956+19571957+ def test_toElementInstructionsMultiple(self):
19581958+@@ -593,10 +592,10 @@ class FormTest(unittest.TestCase):
19591959+ instructions2 = elements[1]
19601960+ self.assertEqual('instructions', instructions1.name)
19611961+ self.assertEqual(NS_X_DATA, instructions1.uri)
19621962+- self.assertEqual('Fill out this form!', unicode(instructions1))
19631963++ self.assertEqual('Fill out this form!', str(instructions1))
19641964+ self.assertEqual('instructions', instructions2.name)
19651965+ self.assertEqual(NS_X_DATA, instructions2.uri)
19661966+- self.assertEqual('no really', unicode(instructions2))
19671967++ self.assertEqual('no really', str(instructions2))
19681968+19691969+19701970+ def test_toElementFormType(self):
19711971+@@ -613,7 +612,7 @@ class FormTest(unittest.TestCase):
19721972+ self.assertEqual(NS_X_DATA, formTypeField.uri)
19731973+ self.assertEqual('FORM_TYPE', formTypeField['var'])
19741974+ self.assertEqual('hidden', formTypeField['type'])
19751975+- self.assertEqual('jabber:bot', unicode(formTypeField.value))
19761976++ self.assertEqual('jabber:bot', str(formTypeField.value))
19771977+19781978+19791979+ def test_toElementFields(self):
19801980+@@ -1091,7 +1090,7 @@ class FormTest(unittest.TestCase):
19811981+ self.assertNotIn('features', form)
19821982+19831983+19841984+- def test_iterkeys(self):
19851985++ def test_keys(self):
19861986+ """
19871987+ Iterating over the keys of a form yields all field names.
19881988+ """
19891989+@@ -1101,10 +1100,10 @@ class FormTest(unittest.TestCase):
19901990+ values=['news', 'search'])]
19911991+ form = data_form.Form('submit', fields=fields)
19921992+ self.assertEqual(set(['botname', 'public', 'features']),
19931993+- set(form.iterkeys()))
19941994++ set(form.keys()))
19951995+19961996+19971997+- def test_itervalues(self):
19981998++ def test_values(self):
19991999+ """
20002000+ Iterating over the values of a form yields all field values.
20012001+ """
20022002+@@ -1112,63 +1111,19 @@ class FormTest(unittest.TestCase):
20032003+ data_form.Field('boolean', var='public', value=True)]
20042004+ form = data_form.Form('submit', fields=fields)
20052005+ self.assertEqual(set(['The Jabber Bot', True]),
20062006+- set(form.itervalues()))
20072007+-
20082008+-
20092009+- def test_iteritems(self):
20102010+- """
20112011+- Iterating over the values of a form yields all item tuples.
20122012+- """
20132013+- fields = [data_form.Field(var='botname', value='The Jabber Bot'),
20142014+- data_form.Field('boolean', var='public', value=True)]
20152015+- form = data_form.Form('submit', fields=fields)
20162016+- self.assertEqual(set([('botname', 'The Jabber Bot'),
20172017+- ('public', True)]),
20182018+- set(form.iteritems()))
20192019+-
20202020+-
20212021+- def test_keys(self):
20222022+- """
20232023+- Getting the keys of a form yields a list of field names.
20242024+- """
20252025+- fields = [data_form.Field(var='botname', value='The Jabber Bot'),
20262026+- data_form.Field('boolean', var='public', value=True),
20272027+- data_form.Field('list-multi', var='features',
20282028+- values=['news', 'search'])]
20292029+- form = data_form.Form('submit', fields=fields)
20302030+- keys = form.keys()
20312031+- if not _PY3:
20322032+- self.assertIsInstance(keys, list)
20332033+- self.assertEqual(set(['botname', 'public', 'features']),
20342034+- set(keys))
20352035+-
20362036+-
20372037+- def test_values(self):
20382038+- """
20392039+- Getting the values of a form yields a list of field values.
20402040+- """
20412041+- fields = [data_form.Field(var='botname', value='The Jabber Bot'),
20422042+- data_form.Field('boolean', var='public', value=True)]
20432043+- form = data_form.Form('submit', fields=fields)
20442044+- values = form.values()
20452045+- if not _PY3:
20462046+- self.assertIsInstance(values, list)
20472047+- self.assertEqual(set(['The Jabber Bot', True]), set(values))
20482048++ set(form.values()))
20492049+20502050+20512051+ def test_items(self):
20522052+ """
20532053+- Iterating over the values of a form yields a list of all item tuples.
20542054++ Iterating over the values of a form yields all item tuples.
20552055+ """
20562056+ fields = [data_form.Field(var='botname', value='The Jabber Bot'),
20572057+ data_form.Field('boolean', var='public', value=True)]
20582058+ form = data_form.Form('submit', fields=fields)
20592059+- items = form.items()
20602060+- if not _PY3:
20612061+- self.assertIsInstance(items, list)
20622062+ self.assertEqual(set([('botname', 'The Jabber Bot'),
20632063+ ('public', True)]),
20642064+- set(items))
20652065++ set(form.items()))
20662066+20672067+20682068+ def test_getValues(self):
20692069+diff --git a/wokkel/test/test_generic.py b/wokkel/test/test_generic.py
20702070+index 94c39e5..4e4ab45 100644
20712071+--- a/wokkel/test/test_generic.py
20722072++++ b/wokkel/test/test_generic.py
20732073+@@ -7,19 +7,12 @@ Tests for L{wokkel.generic}.
20742074+20752075+ from __future__ import division, absolute_import
20762076+20772077+-import re
20782078+-
20792079+ from zope.interface.verify import verifyObject
20802080+20812081+-from twisted.python import deprecate
20822082+-from twisted.python.compat import unicode
20832083+ from twisted.trial import unittest
20842084+-from twisted.trial.util import suppress as SUPPRESS
20852085+ from twisted.words.xish import domish
20862086+ from twisted.words.protocols.jabber.jid import JID
20872087+20882088+-from incremental import Version
20892089+-
20902090+ from wokkel import generic
20912091+ from wokkel.iwokkel import IDisco
20922092+ from wokkel.test.helpers import XmlStreamStub
20932093+@@ -66,11 +59,11 @@ class VersionHandlerTest(unittest.TestCase):
20942094+ elements = list(domish.generateElementsQNamed(response.query.children,
20952095+ 'name', NS_VERSION))
20962096+ self.assertEquals(1, len(elements))
20972097+- self.assertEquals('Test', unicode(elements[0]))
20982098++ self.assertEquals('Test', str(elements[0]))
20992099+ elements = list(domish.generateElementsQNamed(response.query.children,
21002100+ 'version', NS_VERSION))
21012101+ self.assertEquals(1, len(elements))
21022102+- self.assertEquals('0.1.0', unicode(elements[0]))
21032103++ self.assertEquals('0.1.0', str(elements[0]))
21042104+21052105+21062106+21072107+@@ -314,67 +307,3 @@ class RequestTest(unittest.TestCase):
21082108+21092109+ request = SetRequest()
21102110+ self.assertEqual('set', request.stanzaType)
21112111+-
21122112+-
21132113+-
21142114+-class PrepareIDNNameTests(unittest.TestCase):
21152115+- """
21162116+- Tests for L{wokkel.generic.prepareIDNName}.
21172117+- """
21182118+-
21192119+- suppress = [SUPPRESS(category=DeprecationWarning,
21202120+- message=re.escape(
21212121+- deprecate.getDeprecationWarningString(
21222122+- generic.prepareIDNName,
21232123+- Version("wokkel", 18, 0, 0),
21242124+- replacement="unicode.encode('idna')")))]
21252125+-
21262126+-
21272127+- def test_deprecated(self):
21282128+- """
21292129+- prepareIDNName is deprecated.
21302130+- """
21312131+- self.callDeprecated((Version("wokkel", 18, 0, 0),
21322132+- "unicode.encode('idna')"),
21332133+- generic.prepareIDNName, ("example.com"))
21342134+- test_deprecated.suppress = []
21352135+-
21362136+-
21372137+- def test_unicode(self):
21382138+- """
21392139+- A unicode all-ASCII name is converted to an ASCII byte string.
21402140+- """
21412141+- name = u"example.com"
21422142+- result = generic.prepareIDNName(name)
21432143+- self.assertEqual(b"example.com", result)
21442144+-
21452145+-
21462146+- def test_unicodeNonASCII(self):
21472147+- """
21482148+- A unicode with non-ASCII is converted to its ACE equivalent.
21492149+- """
21502150+- name = u"\u00e9chec.example.com"
21512151+- result = generic.prepareIDNName(name)
21522152+- self.assertEqual(b"xn--chec-9oa.example.com", result)
21532153+-
21542154+-
21552155+- def test_unicodeHalfwidthIdeographicFullStop(self):
21562156+- """
21572157+- Exotic dots in unicode names are converted to Full Stop.
21582158+- """
21592159+- name = u"\u00e9chec.example\uff61com"
21602160+- result = generic.prepareIDNName(name)
21612161+- self.assertEqual(b"xn--chec-9oa.example.com", result)
21622162+-
21632163+-
21642164+- def test_unicodeTrailingDot(self):
21652165+- """
21662166+- Unicode names with trailing dots retain the trailing dot.
21672167+-
21682168+- L{encodings.idna.ToASCII} doesn't allow the empty string as the input,
21692169+- hence the implementation needs to strip a trailing dot, and re-add it
21702170+- after encoding the labels.
21712171+- """
21722172+- name = u"example.com."
21732173+- result = generic.prepareIDNName(name)
21742174+- self.assertEqual(b"example.com.", result)
21752175+diff --git a/wokkel/test/test_muc.py b/wokkel/test/test_muc.py
21762176+index f690d05..282a8a1 100644
21772177+--- a/wokkel/test/test_muc.py
21782178++++ b/wokkel/test/test_muc.py
21792179+@@ -14,7 +14,6 @@ from zope.interface import verify
21802180+21812181+ from twisted.trial import unittest
21822182+ from twisted.internet import defer, task
21832183+-from twisted.python.compat import iteritems, unicode
21842184+ from twisted.words.xish import domish, xpath
21852185+ from twisted.words.protocols.jabber.jid import JID
21862186+ from twisted.words.protocols.jabber.error import StanzaError
21872187+@@ -81,7 +80,7 @@ class StatusCodeTest(unittest.TestCase):
21882188+ 332: 'removed-shutdown',
21892189+ }
21902190+21912191+- for code, condition in iteritems(codes):
21922192++ for code, condition in codes.items():
21932193+ constantName = condition.replace('-', '_').upper()
21942194+ self.assertEqual(getattr(muc.STATUS_CODE, constantName),
21952195+ muc.STATUS_CODE.lookupByValue(code))
21962196+@@ -757,7 +756,7 @@ class MUCClientProtocolTest(unittest.TestCase):
21972197+ self.assertEquals('message', message.name)
21982198+ self.assertEquals(self.roomJID.full(), message.getAttribute('to'))
21992199+ self.assertEquals('groupchat', message.getAttribute('type'))
22002200+- self.assertEquals(u'This is a test', unicode(message.body))
22012201++ self.assertEquals(u'This is a test', str(message.body))
22022202+22032203+22042204+ def test_chat(self):
22052205+@@ -773,7 +772,7 @@ class MUCClientProtocolTest(unittest.TestCase):
22062206+ self.assertEquals('message', message.name)
22072207+ self.assertEquals(otherOccupantJID.full(), message.getAttribute('to'))
22082208+ self.assertEquals('chat', message.getAttribute('type'))
22092209+- self.assertEquals(u'This is a test', unicode(message.body))
22102210++ self.assertEquals(u'This is a test', str(message.body))
22112211+22122212+22132213+ def test_subject(self):
22142214+@@ -787,7 +786,7 @@ class MUCClientProtocolTest(unittest.TestCase):
22152215+ self.assertEquals('message', message.name)
22162216+ self.assertEquals(self.roomJID.full(), message.getAttribute('to'))
22172217+ self.assertEquals('groupchat', message.getAttribute('type'))
22182218+- self.assertEquals(u'This is a test', unicode(message.subject))
22192219++ self.assertEquals(u'This is a test', str(message.subject))
22202220+22212221+22222222+ def test_invite(self):
22232223+@@ -806,7 +805,7 @@ class MUCClientProtocolTest(unittest.TestCase):
22242224+ self.assertEquals(muc.NS_MUC_USER, message.x.invite.uri)
22252225+ self.assertEquals(invitee.full(), message.x.invite.getAttribute('to'))
22262226+ self.assertEquals(muc.NS_MUC_USER, message.x.invite.reason.uri)
22272227+- self.assertEquals(u'This is a test', unicode(message.x.invite.reason))
22282228++ self.assertEquals(u'This is a test', str(message.x.invite.reason))
22292229+22302230+22312231+ def test_getRegisterForm(self):
22322232+@@ -1399,7 +1398,7 @@ class MUCClientProtocolTest(unittest.TestCase):
22332233+ nodes = xpath.queryForNodes(query, iq)
22342234+ self.assertNotIdentical(None, nodes, 'Bad configure request')
22352235+ destroy = nodes[0]
22362236+- self.assertEquals('Time to leave', unicode(destroy.reason))
22372237++ self.assertEquals('Time to leave', str(destroy.reason))
22382238+22392239+ response = toResponse(iq, 'result')
22402240+ self.stub.send(response)
22412241+diff --git a/wokkel/test/test_server.py b/wokkel/test/test_server.py
22422242+index 3e3c923..1efb6e5 100644
22432243+--- a/wokkel/test/test_server.py
22442244++++ b/wokkel/test/test_server.py
22452245+@@ -8,7 +8,11 @@ Tests for L{wokkel.server}.
22462246+ from __future__ import division, absolute_import
22472247+ from twisted.internet import defer
22482248+ from twisted.python import failure
22492249+-from twisted.test.proto_helpers import StringTransport
22502250++try:
22512251++ from twisted.internet.testing import StringTransport
22522252++except ImportError:
22532253++ from twisted.test.proto_helpers import StringTransport
22542254++
22552255+ from twisted.trial import unittest
22562256+ from twisted.words.protocols.jabber import error, jid, xmlstream
22572257+ from twisted.words.xish import domish
22582258+diff --git a/wokkel/test/test_shim.py b/wokkel/test/test_shim.py
22592259+index ded4679..d3b76cf 100644
22602260+--- a/wokkel/test/test_shim.py
22612261++++ b/wokkel/test/test_shim.py
22622262+@@ -9,7 +9,6 @@ Tests for {wokkel.shim}.
22632263+22642264+ from __future__ import division, absolute_import
22652265+22662266+-from twisted.python.compat import unicode
22672267+ from twisted.trial import unittest
22682268+22692269+ from wokkel import shim
22702270+@@ -36,7 +35,7 @@ class HeadersTest(unittest.TestCase):
22712271+ self.assertEquals(NS_SHIM, header.uri)
22722272+ self.assertEquals('header', header.name)
22732273+ self.assertEquals('Urgency', header['name'])
22742274+- self.assertEquals('high', unicode(header))
22752275++ self.assertEquals('high', str(header))
22762276+22772277+22782278+ def test_headerRepeated(self):
22792279+@@ -47,7 +46,7 @@ class HeadersTest(unittest.TestCase):
22802280+ ('Collection', 'node2')])
22812281+ elements = list(headers.elements())
22822282+ self.assertEquals(2, len(elements))
22832283+- collections = set((unicode(element) for element in elements
22842284++ collections = set((str(element) for element in elements
22852285+ if element['name'] == 'Collection'))
22862286+ self.assertIn('node1', collections)
22872287+ self.assertIn('node2', collections)
22882288+diff --git a/wokkel/test/test_xmppim.py b/wokkel/test/test_xmppim.py
22892289+index faab8ed..0d4fdbf 100644
22902290+--- a/wokkel/test/test_xmppim.py
22912291++++ b/wokkel/test/test_xmppim.py
22922292+@@ -9,7 +9,6 @@ from __future__ import division, absolute_import
22932293+22942294+ from twisted.internet import defer
22952295+ from twisted.trial import unittest
22962296+-from twisted.python.compat import unicode
22972297+ from twisted.words.protocols.jabber import error
22982298+ from twisted.words.protocols.jabber.jid import JID
22992299+ from twisted.words.protocols.jabber.xmlstream import toResponse
23002300+@@ -55,7 +54,7 @@ class PresenceClientProtocolTest(unittest.TestCase):
23012301+ self.assertEquals(None, presence.uri)
23022302+ self.assertEquals("user@example.com", presence.getAttribute('to'))
23032303+ self.assertEquals("unavailable", presence.getAttribute('type'))
23042304+- self.assertEquals("Disconnected", unicode(presence.status))
23052305++ self.assertEquals("Disconnected", str(presence.status))
23062306+23072307+ def test_unavailableBroadcast(self):
23082308+ """
23092309+@@ -298,9 +297,9 @@ class PresenceProtocolTest(unittest.TestCase):
23102310+ element = self.output[-1]
23112311+ self.assertEquals("user@example.com", element.getAttribute('to'))
23122312+ self.assertIdentical(None, element.getAttribute('type'))
23132313+- self.assertEquals(u'chat', unicode(element.show))
23142314+- self.assertEquals(u'Talk to me!', unicode(element.status))
23152315+- self.assertEquals(u'50', unicode(element.priority))
23162316++ self.assertEquals(u'chat', str(element.show))
23172317++ self.assertEquals(u'Talk to me!', str(element.status))
23182318++ self.assertEquals(u'50', str(element.priority))
23192319+23202320+ def test_availableLanguages(self):
23212321+ """
23222322+@@ -314,19 +313,19 @@ class PresenceProtocolTest(unittest.TestCase):
23232323+ element = self.output[-1]
23242324+ self.assertEquals("user@example.com", element.getAttribute('to'))
23252325+ self.assertIdentical(None, element.getAttribute('type'))
23262326+- self.assertEquals(u'chat', unicode(element.show))
23272327++ self.assertEquals(u'chat', str(element.show))
23282328+23292329+ statuses = {}
23302330+ for status in element.elements():
23312331+ if status.name == 'status':
23322332+ lang = status.getAttribute((NS_XML, 'lang'))
23332333+- statuses[lang] = unicode(status)
23342334++ statuses[lang] = str(status)
23352335+23362336+ self.assertIn(None, statuses)
23372337+ self.assertEquals(u'Talk to me!', statuses[None])
23382338+ self.assertIn('nl', statuses)
23392339+ self.assertEquals(u'Praat met me!', statuses['nl'])
23402340+- self.assertEquals(u'50', unicode(element.priority))
23412341++ self.assertEquals(u'50', str(element.priority))
23422342+23432343+23442344+ def test_availableSender(self):
23452345+@@ -363,7 +362,7 @@ class PresenceProtocolTest(unittest.TestCase):
23462346+ self.assertEquals(None, element.uri)
23472347+ self.assertEquals("user@example.com", element.getAttribute('to'))
23482348+ self.assertEquals("unavailable", element.getAttribute('type'))
23492349+- self.assertEquals("Disconnected", unicode(element.status))
23502350++ self.assertEquals("Disconnected", str(element.status))
23512351+23522352+23532353+ def test_unavailableBroadcast(self):
23542354+@@ -568,7 +567,7 @@ class RosterItemTest(unittest.TestCase):
23552355+ foundGroups = set()
23562356+ for child in element.elements():
23572357+ if child.uri == NS_ROSTER and child.name == 'group':
23582358+- foundGroups.add(unicode(child))
23592359++ foundGroups.add(str(child))
23602360+23612361+ self.assertEqual(groups, foundGroups)
23622362+23632363+diff --git a/wokkel/xmppim.py b/wokkel/xmppim.py
23642364+index e6af929..683577b 100644
23652365+--- a/wokkel/xmppim.py
23662366++++ b/wokkel/xmppim.py
23672367+@@ -15,7 +15,6 @@ from __future__ import division, absolute_import
23682368+ import warnings
23692369+23702370+ from twisted.internet import defer
23712371+-from twisted.python.compat import iteritems, itervalues, unicode
23722372+ from twisted.words.protocols.jabber import error
23732373+ from twisted.words.protocols.jabber.jid import JID
23742374+ from twisted.words.xish import domish
23752375+@@ -48,20 +47,20 @@ class AvailablePresence(Presence):
23762376+ self.addElement('show', content=show)
23772377+23782378+ if statuses is not None:
23792379+- for lang, status in iteritems(statuses):
23802380++ for lang, status in statuses.items():
23812381+ s = self.addElement('status', content=status)
23822382+ if lang:
23832383+ s[(NS_XML, "lang")] = lang
23842384+23852385+ if priority != 0:
23862386+- self.addElement('priority', content=unicode(int(priority)))
23872387++ self.addElement('priority', content=str(int(priority)))
23882388+23892389+ class UnavailablePresence(Presence):
23902390+ def __init__(self, to=None, statuses=None):
23912391+ Presence.__init__(self, to, type='unavailable')
23922392+23932393+ if statuses is not None:
23942394+- for lang, status in iteritems(statuses):
23952395++ for lang, status in statuses.items():
23962396+ s = self.addElement('status', content=status)
23972397+ if lang:
23982398+ s[(NS_XML, "lang")] = lang
23992399+@@ -76,7 +75,7 @@ class PresenceClientProtocol(XMPPHandler):
24002400+ for element in presence.elements():
24012401+ if element.name == 'status':
24022402+ lang = element.getAttribute((NS_XML, 'lang'))
24032403+- text = unicode(element)
24042404++ text = str(element)
24052405+ statuses[lang] = text
24062406+ return statuses
24072407+24082408+@@ -92,14 +91,14 @@ class PresenceClientProtocol(XMPPHandler):
24092409+ def _onPresenceAvailable(self, presence):
24102410+ entity = JID(presence["from"])
24112411+24122412+- show = unicode(presence.show or '')
24132413++ show = str(presence.show or '')
24142414+ if show not in ['away', 'xa', 'chat', 'dnd']:
24152415+ show = None
24162416+24172417+ statuses = self._getStatuses(presence)
24182418+24192419+ try:
24202420+- priority = int(unicode(presence.priority or '')) or 0
24212421++ priority = int(str(presence.priority or '')) or 0
24222422+ except ValueError:
24232423+ priority = 0
24242424+24252425+@@ -133,14 +132,14 @@ class PresenceClientProtocol(XMPPHandler):
24262426+ @type entity: {JID}
24272427+ @param show: detailed presence information. One of C{'away'}, C{'xa'},
24282428+ C{'chat'}, C{'dnd'} or C{None}.
24292429+- @type show: C{str} or C{NoneType}
24302430++ @type show: L{str} or C{NoneType}
24312431+ @param statuses: dictionary of natural language descriptions of the
24322432+ availability status, keyed by the language
24332433+ descriptor. A status without a language
24342434+ specified, is keyed with C{None}.
24352435+- @type statuses: C{dict}
24362436++ @type statuses: L{dict}
24372437+ @param priority: priority level of the resource.
24382438+- @type priority: C{int}
24392439++ @type priority: L{int}
24402440+ """
24412441+24422442+ def unavailableReceived(self, entity, statuses=None):
24432443+@@ -153,7 +152,7 @@ class PresenceClientProtocol(XMPPHandler):
24442444+ availability status, keyed by the language
24452445+ descriptor. A status without a language
24462446+ specified, is keyed with C{None}.
24472447+- @type statuses: C{dict}
24482448++ @type statuses: L{dict}
24492449+ """
24502450+24512451+ def subscribedReceived(self, entity):
24522452+@@ -196,14 +195,14 @@ class PresenceClientProtocol(XMPPHandler):
24532453+ @type entity: {JID}
24542454+ @param show: optional detailed presence information. One of C{'away'},
24552455+ C{'xa'}, C{'chat'}, C{'dnd'}.
24562456+- @type show: C{str}
24572457++ @type show: L{str}
24582458+ @param statuses: dictionary of natural language descriptions of the
24592459+ availability status, keyed by the language
24602460+ descriptor. A status without a language
24612461+ specified, is keyed with C{None}.
24622462+- @type statuses: C{dict}
24632463++ @type statuses: L{dict}
24642464+ @param priority: priority level of the resource.
24652465+- @type priority: C{int}
24662466++ @type priority: L{int}
24672467+ """
24682468+ self.send(AvailablePresence(entity, show, statuses, priority))
24692469+24702470+@@ -217,7 +216,7 @@ class PresenceClientProtocol(XMPPHandler):
24712471+ availability status, keyed by the language
24722472+ descriptor. A status without a language
24732473+ specified, is keyed with C{None}.
24742474+- @type statuses: C{dict}
24752475++ @type statuses: L{dict}
24762476+ """
24772477+ self.send(UnavailablePresence(entity, statuses))
24782478+24792479+@@ -275,19 +274,19 @@ class AvailabilityPresence(BasePresence):
24802480+ L{SubscriptionPresence}).
24812481+24822482+ @ivar available: The availability being communicated.
24832483+- @type available: C{bool}
24842484++ @type available: L{bool}
24852485+ @ivar show: More specific availability. Can be one of C{'chat'}, C{'away'},
24862486+ C{'xa'}, C{'dnd'} or C{None}.
24872487+- @type show: C{str} or C{NoneType}
24882488++ @type show: L{str} or C{NoneType}
24892489+ @ivar statuses: Natural language texts to detail the (un)availability.
24902490+ These are represented as a mapping from language code
24912491+- (C{str} or C{None}) to the corresponding text (C{unicode}).
24922492++ (L{str} or C{None}) to the corresponding text (L{str}).
24932493+ If the key is C{None}, the associated text is in the
24942494+ default language.
24952495+- @type statuses: C{dict}
24962496++ @type statuses: L{dict}
24972497+ @ivar priority: Priority level for this resource. Must be between -128 and
24982498+ 127. Defaults to 0.
24992499+- @type priority: C{int}
25002500++ @type priority: L{int}
25012501+ """
25022502+25032503+ childParsers = {(None, 'show'): '_childParser_show',
25042504+@@ -309,7 +308,7 @@ class AvailabilityPresence(BasePresence):
25052505+ if None in self.statuses:
25062506+ return self.statuses[None]
25072507+ elif self.statuses:
25082508+- for status in itervalues(self.status):
25092509++ for status in self.status.values():
25102510+ return status
25112511+ else:
25122512+ return None
25132513+@@ -318,20 +317,20 @@ class AvailabilityPresence(BasePresence):
25142514+25152515+25162516+ def _childParser_show(self, element):
25172517+- show = unicode(element)
25182518++ show = str(element)
25192519+ if show in ('chat', 'away', 'xa', 'dnd'):
25202520+ self.show = show
25212521+25222522+25232523+ def _childParser_status(self, element):
25242524+ lang = element.getAttribute((NS_XML, 'lang'), None)
25252525+- text = unicode(element)
25262526++ text = str(element)
25272527+ self.statuses[lang] = text
25282528+25292529+25302530+ def _childParser_priority(self, element):
25312531+ try:
25322532+- self.priority = int(unicode(element))
25332533++ self.priority = int(str(element))
25342534+ except ValueError:
25352535+ pass
25362536+25372537+@@ -353,9 +352,9 @@ class AvailabilityPresence(BasePresence):
25382538+ if self.show in ('chat', 'away', 'xa', 'dnd'):
25392539+ presence.addElement('show', content=self.show)
25402540+ if self.priority != 0:
25412541+- presence.addElement('priority', content=unicode(self.priority))
25422542++ presence.addElement('priority', content=str(self.priority))
25432543+25442544+- for lang, text in iteritems(self.statuses):
25452545++ for lang, text in self.statuses.items():
25462546+ status = presence.addElement('status', content=text)
25472547+ if lang:
25482548+ status[(NS_XML, 'lang')] = lang
25492549+@@ -400,7 +399,7 @@ class BasePresenceProtocol(XMPPHandler):
25502550+25512551+ @cvar presenceTypeParserMap: Maps presence stanza types to their respective
25522552+ stanza parser classes (derived from L{Stanza}).
25532553+- @type presenceTypeParserMap: C{dict}
25542554++ @type presenceTypeParserMap: L{dict}
25552555+ """
25562556+25572557+ presenceTypeParserMap = {}
25582558+@@ -515,15 +514,15 @@ class PresenceProtocol(BasePresenceProtocol):
25592559+25602560+ @param show: Optional detailed presence information. One of C{'away'},
25612561+ C{'xa'}, C{'chat'}, C{'dnd'}.
25622562+- @type show: C{str}
25632563++ @type show: L{str}
25642564+25652565+ @param statuses: Mapping of natural language descriptions of the
25662566+ availability status, keyed by the language descriptor. A status
25672567+ without a language specified, is keyed with C{None}.
25682568+- @type statuses: C{dict}
25692569++ @type statuses: L{dict}
25702570+25712571+ @param priority: priority level of the resource.
25722572+- @type priority: C{int}
25732573++ @type priority: L{int}
25742574+ """
25752575+ presence = AvailabilityPresence(recipient=recipient, sender=sender,
25762576+ show=show, statuses=statuses,
25772577+@@ -541,7 +540,7 @@ class PresenceProtocol(BasePresenceProtocol):
25782578+ @param statuses: dictionary of natural language descriptions of the
25792579+ availability status, keyed by the language descriptor. A status
25802580+ without a language specified, is keyed with C{None}.
25812581+- @type statuses: C{dict}
25822582++ @type statuses: L{dict}
25832583+ """
25842584+ presence = AvailabilityPresence(recipient=recipient, sender=sender,
25852585+ available=False, statuses=statuses)
25862586+@@ -617,25 +616,25 @@ class RosterItem(object):
25872587+ @ivar entity: The JID of the contact.
25882588+ @type entity: L{JID}
25892589+ @ivar name: The associated nickname for this contact.
25902590+- @type name: C{unicode}
25912591++ @type name: L{str}
25922592+ @ivar subscriptionTo: Subscription state to contact's presence. If C{True},
25932593+ the roster owner is subscribed to the presence
25942594+ information of the contact.
25952595+- @type subscriptionTo: C{bool}
25962596++ @type subscriptionTo: L{bool}
25972597+ @ivar subscriptionFrom: Contact's subscription state. If C{True}, the
25982598+ contact is subscribed to the presence information
25992599+ of the roster owner.
26002600+- @type subscriptionFrom: C{bool}
26012601++ @type subscriptionFrom: L{bool}
26022602+ @ivar pendingOut: Whether the subscription request to this contact is
26032603+ pending.
26042604+- @type pendingOut: C{bool}
26052605++ @type pendingOut: L{bool}
26062606+ @ivar groups: Set of groups this contact is categorized in. Groups are
26072607+- represented by an opaque identifier of type C{unicode}.
26082608+- @type groups: C{set}
26092609++ represented by an opaque identifier of type L{str}.
26102610++ @type groups: L{set}
26112611+ @ivar approved: Signals pre-approved subscription.
26122612+- @type approved: C{bool}
26132613++ @type approved: L{bool}
26142614+ @ivar remove: Signals roster item removal.
26152615+- @type remove: C{bool}
26162616++ @type remove: L{bool}
26172617+ """
26182618+26192619+ __subscriptionStates = {(False, False): None,
26202620+@@ -755,7 +754,7 @@ class RosterItem(object):
26212621+ item.approved = element.getAttribute('approved') in ('true', '1')
26222622+ for subElement in domish.generateElementsQNamed(element.children,
26232623+ 'group', NS_ROSTER):
26242624+- item.groups.add(unicode(subElement))
26252625++ item.groups.add(str(subElement))
26262626+ return item
26272627+26282628+26292629+@@ -771,7 +770,7 @@ class RosterRequest(Request):
26302630+ retrieving the roster as a delta from a known cached version. This
26312631+ should only be set if the recipient is known to support roster
26322632+ versioning.
26332633+- @type version: C{unicode}
26342634++ @type version: L{str}
26352635+26362636+ @ivar rosterSet: If set, this is a roster set request. This flag is used
26372637+ to make sure some attributes of the roster item are not rendered by
26382638+@@ -821,7 +820,7 @@ class Roster(dict):
26392639+ identifier for this version of the roster.
26402640+26412641+ @ivar version: Roster version identifier.
26422642+- @type version: C{unicode}.
26432643++ @type version: L{str}.
26442644+ """
26452645+26462646+ version = None
26472647+@@ -892,7 +891,7 @@ class RosterClientProtocol(XMPPHandler, IQHandlerMixin):
26482648+ known to support roster versioning. If there is no (valid) cached
26492649+ version of the roster, but roster versioning is desired,
26502650+ C{version} should be set to the empty string (C{u''}).
26512651+- @type version: C{unicode}
26522652++ @type version: L{str}
26532653+26542654+ @return: Roster as a mapping from L{JID} to L{RosterItem}.
26552655+ @rtype: L{twisted.internet.defer.Deferred}
26562656+@@ -1023,11 +1022,11 @@ class Message(Stanza):
26572657+26582658+26592659+ def _childParser_body(self, element):
26602660+- self.body = unicode(element)
26612661++ self.body = str(element)
26622662+26632663+26642664+ def _childParser_subject(self, element):
26652665+- self.subject = unicode(element)
26662666++ self.subject = str(element)
26672667+26682668+26692669+ def toElement(self):
26702670+--
26712671+2.44.1