Changes in [225:58dd11c3ddd5:226:2532cfb12c7c]
- Files:
-
- 1 added
- 37 edited
Legend:
- Unmodified
- Added
- Removed
-
.travis.yml
r187 r211 2 2 3 3 python: 4 - 2.65 4 - 2.7 5 - 3.3 6 - 3.5 6 7 - pypy 7 8 … … 10 11 - PYFLAKES_NODOCTEST=1 11 12 matrix: 12 - TWISTED=Twisted==12.3 13 - TWISTED=svn+svn://svn.twistedmatrix.com/svn/Twisted/trunk 13 - TWISTED=Twisted==15.5 14 - TWISTED=Twisted==16.4 15 - TWISTED=https://github.com/twisted/twisted/archive/trunk.zip 16 17 matrix: 18 exclude: 19 - python: 3.3 20 env: TWISTED=Twisted==15.5 21 - python: 3.5 22 env: TWISTED=Twisted==15.5 14 23 15 24 install: 16 - pip install pyflakes --use-mirrors17 - pip install -q $TWISTED --use-mirrors25 - pip install pyflakes 26 - pip install -q $TWISTED 18 27 - python setup.py install 19 28 -
doc/examples/echo_server.tac
r69 r207 9 9 10 10 from twisted.application import service, strports 11 from twisted.python.compat import unicode 11 12 from twisted.words.protocols.jabber.xmlstream import toResponse 12 13 from wokkel import component, server, xmppim -
doc/examples/pinger.py
r65 r207 16 16 def connectionInitialized(self): 17 17 def cb(response): 18 print "*** Pong ***"18 print("*** Pong ***") 19 19 20 print "*** Ping ***"20 print("*** Ping ***") 21 21 d = self.ping(self.entity, sender=self.sender) 22 22 d.addCallback(cb) -
setup.py
r179 r214 4 4 # See LICENSE for details. 5 5 6 import sys 6 7 from setuptools import setup 7 8 … … 28 29 egg_info.write_toplevel_names = _hacked_write_toplevel_names 29 30 31 if sys.version_info < (3, 0): 32 requiredTwisted = "15.5.0" 33 else: 34 requiredTwisted = "16.4.0" 35 30 36 setup(name='wokkel', 31 37 version='0.7.1', … … 45 51 zip_safe=False, 46 52 install_requires=[ 47 'Twisted >= 10.0.0',53 'Twisted >= %s' % requiredTwisted, 48 54 'python-dateutil', 49 55 ], -
wokkel/client.py
r184 r208 10 10 that should probably eventually move there. 11 11 """ 12 13 from __future__ import division, absolute_import 12 14 13 15 from twisted.application import service -
wokkel/compat.py
r165 r204 8 8 """ 9 9 10 __all__ = ['BootstrapMixin', 'XmlStreamServerFactory', 'IQ', 11 'NamedConstant', 'ValueConstant', 'Names', 'Values'] 10 from __future__ import division, absolute_import 12 11 13 from itertools import count14 15 from twisted.python.deprecate import deprecatedModuleAttribute16 from twisted.python.versions import Version17 12 from twisted.words.protocols.jabber import xmlstream 18 from twisted.words.protocols.jabber.xmlstream import XmlStreamServerFactory19 from twisted.words.xish.xmlstream import BootstrapMixin20 21 deprecatedModuleAttribute(22 Version("Wokkel", 0, 7, 0),23 "Use twisted.words.xish.xmlstream.BootstrapMixin instead.",24 __name__,25 "BootstrapMixin")26 27 deprecatedModuleAttribute(28 Version("Wokkel", 0, 7, 0),29 "Use twisted.words.protocols.jabber.xmlstream.XmlStreamServerFactory "30 "instead.",31 __name__,32 "XmlStreamServerFactory")33 13 34 14 class IQ(xmlstream.IQ): … … 54 34 55 35 56 _unspecified = object() 57 _constantOrder = count().next 58 59 60 class _Constant(object): 61 """ 62 @ivar _index: A C{int} allocated from a shared counter in order to keep 63 track of the order in which L{_Constant}s are instantiated. 64 65 @ivar name: A C{str} giving the name of this constant; only set once the 66 constant is initialized by L{_ConstantsContainer}. 67 68 @ivar _container: The L{_ConstantsContainer} subclass this constant belongs 69 to; only set once the constant is initialized by that subclass. 70 71 @since: Twisted 12.0.0. 72 """ 73 def __init__(self): 74 self._index = _constantOrder() 75 76 77 def __get__(self, oself, cls): 78 """ 79 Ensure this constant has been initialized before returning it. 80 """ 81 cls._initializeEnumerants() 82 return self 83 84 85 def __repr__(self): 86 """ 87 Return text identifying both which constant this is and which collection 88 it belongs to. 89 """ 90 return "<%s=%s>" % (self._container.__name__, self.name) 91 92 93 def _realize(self, container, name, value): 94 """ 95 Complete the initialization of this L{_Constant}. 96 97 @param container: The L{_ConstantsContainer} subclass this constant is 98 part of. 99 100 @param name: The name of this constant in its container. 101 102 @param value: The value of this constant; not used, as named constants 103 have no value apart from their identity. 104 """ 105 self._container = container 106 self.name = name 107 108 109 110 class _EnumerantsInitializer(object): 111 """ 112 L{_EnumerantsInitializer} is a descriptor used to initialize a cache of 113 objects representing named constants for a particular L{_ConstantsContainer} 114 subclass. 115 116 @since: Twisted 12.0.0. 117 """ 118 def __get__(self, oself, cls): 119 """ 120 Trigger the initialization of the enumerants cache on C{cls} and then 121 return it. 122 """ 123 cls._initializeEnumerants() 124 return cls._enumerants 125 126 127 128 class _ConstantsContainer(object): 129 """ 130 L{_ConstantsContainer} is a class with attributes used as symbolic 131 constants. It is up to subclasses to specify what kind of constants are 132 allowed. 133 134 @cvar _constantType: Specified by a L{_ConstantsContainer} subclass to 135 specify the type of constants allowed by that subclass. 136 137 @cvar _enumerantsInitialized: A C{bool} tracking whether C{_enumerants} has 138 been initialized yet or not. 139 140 @cvar _enumerants: A C{dict} mapping the names of constants (eg 141 L{NamedConstant} instances) found in the class definition to those 142 instances. This is initialized via the L{_EnumerantsInitializer} 143 descriptor the first time it is accessed. 144 145 @since: Twisted 12.0.0. 146 """ 147 _constantType = None 148 149 _enumerantsInitialized = False 150 _enumerants = _EnumerantsInitializer() 151 152 def __new__(cls): 153 """ 154 Classes representing constants containers are not intended to be 155 instantiated. 156 157 The class object itself is used directly. 158 """ 159 raise TypeError("%s may not be instantiated." % (cls.__name__,)) 160 161 162 def _initializeEnumerants(cls): 163 """ 164 Find all of the L{NamedConstant} instances in the definition of C{cls}, 165 initialize them with constant values, and build a mapping from their 166 names to them to attach to C{cls}. 167 """ 168 if not cls._enumerantsInitialized: 169 constants = [] 170 for (name, descriptor) in cls.__dict__.iteritems(): 171 if isinstance(descriptor, cls._constantType): 172 constants.append((descriptor._index, name, descriptor)) 173 enumerants = {} 174 for (index, enumerant, descriptor) in constants: 175 value = cls._constantFactory(enumerant) 176 descriptor._realize(cls, enumerant, value) 177 enumerants[enumerant] = descriptor 178 # Replace the _enumerants descriptor with the result so future 179 # access will go directly to the values. The _enumerantsInitialized 180 # flag is still necessary because NamedConstant.__get__ may also 181 # call this method. 182 cls._enumerants = enumerants 183 cls._enumerantsInitialized = True 184 _initializeEnumerants = classmethod(_initializeEnumerants) 185 186 187 def _constantFactory(cls, name): 188 """ 189 Construct the value for a new constant to add to this container. 190 191 @param name: The name of the constant to create. 192 193 @return: L{NamedConstant} instances have no value apart from identity, 194 so return a meaningless dummy value. 195 """ 196 return _unspecified 197 _constantFactory = classmethod(_constantFactory) 198 199 200 def lookupByName(cls, name): 201 """ 202 Retrieve a constant by its name or raise a C{ValueError} if there is no 203 constant associated with that name. 204 205 @param name: A C{str} giving the name of one of the constants defined by 206 C{cls}. 207 208 @raise ValueError: If C{name} is not the name of one of the constants 209 defined by C{cls}. 210 211 @return: The L{NamedConstant} associated with C{name}. 212 """ 213 if name in cls._enumerants: 214 return getattr(cls, name) 215 raise ValueError(name) 216 lookupByName = classmethod(lookupByName) 217 218 219 def iterconstants(cls): 220 """ 221 Iteration over a L{Names} subclass results in all of the constants it 222 contains. 223 224 @return: an iterator the elements of which are the L{NamedConstant} 225 instances defined in the body of this L{Names} subclass. 226 """ 227 constants = cls._enumerants.values() 228 constants.sort(key=lambda descriptor: descriptor._index) 229 return iter(constants) 230 iterconstants = classmethod(iterconstants) 231 232 233 234 class NamedConstant(_Constant): 235 """ 236 L{NamedConstant} defines an attribute to be a named constant within a 237 collection defined by a L{Names} subclass. 238 239 L{NamedConstant} is only for use in the definition of L{Names} 240 subclasses. Do not instantiate L{NamedConstant} elsewhere and do not 241 subclass it. 242 243 @since: Twisted 12.0.0. 244 """ 245 246 247 248 class Names(_ConstantsContainer): 249 """ 250 A L{Names} subclass contains constants which differ only in their names and 251 identities. 252 253 @since: Twisted 12.0.0. 254 """ 255 _constantType = NamedConstant 256 257 258 259 class ValueConstant(_Constant): 260 """ 261 L{ValueConstant} defines an attribute to be a named constant within a 262 collection defined by a L{Values} subclass. 263 264 L{ValueConstant} is only for use in the definition of L{Values} subclasses. 265 Do not instantiate L{ValueConstant} elsewhere and do not subclass it. 266 267 @since: Twisted 12.0.0. 268 """ 269 def __init__(self, value): 270 _Constant.__init__(self) 271 self.value = value 272 273 274 275 class Values(_ConstantsContainer): 276 """ 277 A L{Values} subclass contains constants which are associated with arbitrary 278 values. 279 280 @since: Twisted 12.0.0. 281 """ 282 _constantType = ValueConstant 283 284 def lookupByValue(cls, value): 285 """ 286 Retrieve a constant by its value or raise a C{ValueError} if there is no 287 constant associated with that value. 288 289 @param value: The value of one of the constants defined by C{cls}. 290 291 @raise ValueError: If C{value} is not the value of one of the constants 292 defined by C{cls}. 293 294 @return: The L{ValueConstant} associated with C{value}. 295 """ 296 for constant in cls.iterconstants(): 297 if constant.value == value: 298 return constant 299 raise ValueError(value) 300 lookupByValue = classmethod(lookupByValue) 36 __all__ = ['IQ'] -
wokkel/component.py
r176 r205 8 8 """ 9 9 10 from __future__ import division, absolute_import 11 10 12 from twisted.application import service 11 13 from twisted.internet import reactor 12 14 from twisted.python import log 15 from twisted.python.compat import unicode 13 16 from twisted.words.protocols.jabber.jid import internJID as JID 14 17 from twisted.words.protocols.jabber import component, error, xmlstream … … 103 106 allows for one-process XMPP servers. 104 107 105 @ivar domains: Domains (as C{str}) this component will handle traffic for. 106 @type domains: C{set} 108 @ivar domains: Domains (as L{unicode}) this component will handle traffic 109 for. 110 @type domains: L{set} 107 111 """ 108 112 … … 174 178 175 179 @ivar secret: The shared used to authorized incoming component connections. 176 @type secret: C{unicode}.180 @type secret: L{unicode}. 177 181 """ 178 182 … … 275 279 stanzas they offer for routing. 276 280 277 A route destination of C{None} adds a default route. Traffic for which no281 A route destination of L{None} adds a default route. Traffic for which no 278 282 specific route exists, will be routed to this default route. 279 283 280 284 @ivar routes: Routes based on the host part of JIDs. Maps host names to the 281 285 L{EventDispatcher<twisted.words.xish.utility.EventDispatcher>}s that 282 should receive the traffic. A key of C{None} means the default route.283 @type routes: C{dict}286 should receive the traffic. A key of L{None} means the default route. 287 @type routes: L{dict} 284 288 """ 285 289 … … 297 301 298 302 @param destination: Destination of the route to be added as a host name 299 or C{None} for the default route.300 @type destination: C{str} or C{NoneType}303 or L{None} for the default route. 304 @type destination: L{unicode} or L{NoneType} 301 305 302 306 @param xs: XML Stream to register the route for. … … 313 317 314 318 @param destination: Destination of the route that should be removed. 315 @type destination: C{str}.319 @type destination: L{unicode} 316 320 317 321 @param xs: XML Stream to remove the route for. -
wokkel/componentservertap.py
r96 r209 9 9 domain(s). 10 10 """ 11 12 from __future__ import division, absolute_import 11 13 12 14 from twisted.application import service, strports -
wokkel/data_form.py
r182 r196 13 13 """ 14 14 15 from zope.interface import implements 15 from __future__ import division, absolute_import 16 17 from zope.interface import implementer 16 18 from zope.interface.common import mapping 19 20 from twisted.python.compat import iteritems, unicode, _PY3 17 21 from twisted.words.protocols.jabber.jid import JID 18 22 from twisted.words.xish import domish … … 48 52 49 53 @ivar value: Value of this option. 50 @type value: C{unicode}54 @type value: L{unicode} 51 55 @ivar label: Optional label for this option. 52 @type label: C{unicode} or C{NoneType}56 @type label: L{unicode} or L{NoneType} 53 57 """ 54 58 … … 101 105 102 106 The default is C{'text-single'}. 103 @type fieldType: C{str}107 @type fieldType: L{str} 104 108 @ivar var: Field name. Optional if C{fieldType} is C{'fixed'}. 105 @type var: C{str}109 @type var: L{str} 106 110 @ivar label: Human readable label for this field. 107 @type label: C{unicode}111 @type label: L{unicode} 108 112 @ivar values: The values for this field, for multi-valued field 109 types, as a list of C{bool}, C{unicode} or L{JID}.110 @type values: C{list}113 types, as a list of L{bool}, L{unicode} or L{JID}. 114 @type values: L{list} 111 115 @ivar options: List of possible values to choose from in a response 112 116 to this form as a list of L{Option}s. 113 @type options: C{list}117 @type options: L{list} 114 118 @ivar desc: Human readable description for this field. 115 @type desc: C{unicode}119 @type desc: L{unicode} 116 120 @ivar required: Whether the field is required to be provided in a 117 121 response to this form. 118 @type required: C{bool}122 @type required: L{bool} 119 123 """ 120 124 … … 127 131 See the identically named instance variables for descriptions. 128 132 129 If C{value} is not C{None}, it overrides C{values}, setting the133 If C{value} is not L{None}, it overrides C{values}, setting the 130 134 given value as the only value for this field. 131 135 """ … … 144 148 self.options = [Option(optionValue, optionLabel) 145 149 for optionValue, optionLabel 146 in options.iteritems()]150 in iteritems(options)] 147 151 except AttributeError: 148 152 self.options = options or [] … … 182 186 Sets C{value} as the only element of L{values}. 183 187 184 @type value: C{bool}, C{unicode} or L{JID}188 @type value: L{bool}, L{unicode} or L{JID} 185 189 """ 186 190 self.values = [value] … … 191 195 Getter of value property. 192 196 193 Returns the first element of L{values}, if present, or C{None}.197 Returns the first element of L{values}, if present, or L{None}. 194 198 """ 195 199 … … 310 314 field = Field(None) 311 315 312 for eAttr, fAttr in {'type': 'fieldType',313 'var': 'var',314 'label': 'label'}.iteritems():316 for eAttr, fAttr in iteritems({'type': 'fieldType', 317 'var': 'var', 318 'label': 'label'}): 315 319 value = element.getAttribute(eAttr) 316 320 if value: … … 347 351 if 'options' in fieldDict: 348 352 options = [] 349 for value, label in fieldDict['options'].iteritems():353 for value, label in iteritems(fieldDict['options']): 350 354 options.append(Option(value, label)) 351 355 kwargs['options'] = options … … 354 358 355 359 360 361 @implementer(mapping.IIterableMapping, 362 mapping.IEnumerableMapping, 363 mapping.IReadMapping, 364 mapping.IItemMapping) 356 365 357 366 class Form(object): … … 374 383 @ivar formType: Type of form. One of C{'form'}, C{'submit'}, {'cancel'}, 375 384 or {'result'}. 376 @type formType: C{str}385 @type formType: L{str} 377 386 378 387 @ivar title: Natural language title of the form. 379 @type title: C{unicode}380 381 @ivar instructions: Natural language instructions as a list of C{unicode}388 @type title: L{unicode} 389 390 @ivar instructions: Natural language instructions as a list of L{unicode} 382 391 strings without line breaks. 383 @type instructions: C{list}392 @type instructions: L{list} 384 393 385 394 @ivar formNamespace: The optional namespace of the field names for this 386 395 form. This goes in the special field named C{'FORM_TYPE'}, if set. 387 @type formNamespace: C{str}396 @type formNamespace: L{str} 388 397 389 398 @ivar fields: Dictionary of named fields. Note that this is meant to be 390 399 used for reading, only. One should use L{addField} or L{makeFields} and 391 400 L{removeField} for adding and removing fields. 392 @type fields: C{dict}401 @type fields: L{dict} 393 402 394 403 @ivar fieldList: List of all fields, in the order they are added. Like 395 404 C{fields}, this is meant to be used for reading, only. 396 @type fieldList: C{list} 397 """ 398 399 implements(mapping.IIterableMapping, 400 mapping.IEnumerableMapping, 401 mapping.IReadMapping, 402 mapping.IItemMapping) 405 @type fieldList: L{list} 406 """ 403 407 404 408 def __init__(self, formType, title=None, instructions=None, … … 469 473 this form. It is typically used for generating outgoing forms. 470 474 471 If C{fieldDefs} is not C{None}, this is used to fill in475 If C{fieldDefs} is not L{None}, this is used to fill in 472 476 additional properties of fields, like the field types, labels and 473 477 possible options. 474 478 475 If C{filterUnknown} is C{True} and C{fieldDefs} is not C{None}, fields479 If C{filterUnknown} is L{True} and C{fieldDefs} is not L{None}, fields 476 480 will only be created from C{values} with a corresponding entry in 477 481 C{fieldDefs}. 478 482 479 If the field type is unknown, the field type is C{None}. When the form483 If the field type is unknown, the field type is L{None}. When the form 480 484 is rendered using L{toElement}, these fields will have no C{'type'} 481 485 attribute, and it is up to the receiving party to interpret the values … … 484 488 485 489 @param values: Values to create fields from. 486 @type values: C{dict}490 @type values: L{dict} 487 491 488 492 @param fieldDefs: Field definitions as a dictionary. See 489 493 L{wokkel.iwokkel.IPubSubService.getConfigurationOptions} 490 @type fieldDefs: C{dict}491 492 @param filterUnknown: If C{True}, ignore fields that are not in494 @type fieldDefs: L{dict} 495 496 @param filterUnknown: If L{True}, ignore fields that are not in 493 497 C{fieldDefs}. 494 @type filterUnknown: C{bool}495 """ 496 for name, value in values.iteritems():498 @type filterUnknown: L{bool} 499 """ 500 for name, value in iteritems(values): 497 501 fieldDict = {'var': name, 498 502 'type': None} … … 634 638 yield (key, self[key]) 635 639 636 637 def keys(self): 638 return list(self) 639 640 641 def values(self): 642 return list(self.itervalues()) 643 644 645 def items(self): 646 return list(self.iteritems()) 640 if _PY3: 641 keys = iterkeys 642 values = itervalues 643 items = iteritems 644 else: 645 def keys(self): 646 return list(self) 647 648 649 def values(self): 650 return list(self.itervalues()) 651 652 653 def items(self): 654 return list(self.iteritems()) 647 655 648 656 … … 653 661 For all named fields, the corresponding value or values are 654 662 returned in a dictionary keyed by the field name. This is equivalent 655 do C{dict(f)}, where C{f} is a L{Form}.663 do L{dict(f)}, where C{f} is a L{Form}. 656 664 657 665 @see: L{__getitem__} 658 @rtype: C{dict}666 @rtype: L{dict} 659 667 """ 660 668 return dict(self) … … 669 677 field definition in C{fieldDefs} is used to check the field type. 670 678 671 If C{filterUnknown} is C{True}, fields that are not present in679 If C{filterUnknown} is L{True}, fields that are not present in 672 680 C{fieldDefs} are removed from the form. 673 681 674 If the field type is C{None} (when not set by the sending entity),682 If the field type is L{None} (when not set by the sending entity), 675 683 the type from the field definitition is used, or C{'text-single'} if 676 684 that is not set. … … 682 690 @param fieldDefs: Field definitions as a dictionary. See 683 691 L{wokkel.iwokkel.IPubSubService.getConfigurationOptions} 684 @type fieldDefs: C{dict}685 686 @param filterUnknown: If C{True}, remove fields that are not in692 @type fieldDefs: L{dict} 693 694 @param filterUnknown: If L{True}, remove fields that are not in 687 695 C{fieldDefs}. 688 @type filterUnknown: C{bool}696 @type filterUnknown: L{bool} 689 697 """ 690 698 … … 694 702 filtered = [] 695 703 696 for name, field in self.fields.iteritems():704 for name, field in iteritems(self.fields): 697 705 if name in fieldDefs: 698 706 fieldDef = fieldDefs[name] -
wokkel/delay.py
r104 r216 11 11 U{XEP-0091<http://xmpp.org/extensions/xep-0091.html>}. 12 12 """ 13 14 from __future__ import division, absolute_import 13 15 14 16 from dateutil.parser import parse … … 79 81 if stamp.tzinfo is None: 80 82 stamp = stamp.replace(tzinfo=tzutc()) 81 except (KeyError, ValueError ):83 except (KeyError, ValueError, TypeError): 82 84 stamp = None 83 85 -
wokkel/disco.py
r166 r198 11 11 """ 12 12 13 from __future__ import division, absolute_import 14 13 15 from twisted.internet import defer 16 from twisted.python.compat import iteritems, unicode 14 17 from twisted.words.protocols.jabber import error, jid 15 18 from twisted.words.xish import domish … … 364 367 } 365 368 366 _verbRequestMap = dict(((v, k) for k, v in _requestVerbMap.iteritems()))369 _verbRequestMap = dict(((v, k) for k, v in iteritems(_requestVerbMap))) 367 370 368 371 def __init__(self, verb=None, nodeIdentifier='', -
wokkel/formats.py
r165 r213 1 # -*- test-case-name: wokkel.test.test_formats -*- 2 # 1 3 # Copyright (c) Ralph Meijer. 2 4 # See LICENSE for details. 5 6 """ 7 Generic payload formats. 8 """ 9 10 from __future__ import division, absolute_import 11 12 from twisted.python.compat import unicode 3 13 4 14 NS_MOOD = 'http://jabber.org/protocol/mood' … … 20 30 self.value = value 21 31 self.text = text 32 22 33 23 34 def fromXml(self, element): … … 55 66 56 67 fromXml = classmethod(fromXml) 68 69 57 70 58 71 class Tune: -
wokkel/generic.py
r185 r195 8 8 """ 9 9 10 from zope.interface import implements 10 from __future__ import division, absolute_import 11 12 from zope.interface import implementer 11 13 12 14 from twisted.internet import defer, protocol … … 87 89 88 90 91 @implementer(IDisco) 89 92 class VersionHandler(XMPPHandler): 90 93 """ … … 94 97 U{XEP-0092<http://xmpp.org/extensions/xep-0092.html>}. 95 98 """ 96 97 implements(IDisco)98 99 99 100 def __init__(self, name, version): … … 114 115 iq.handled = True 115 116 116 def getDiscoInfo(self, requestor, target, node ):117 def getDiscoInfo(self, requestor, target, nodeIdentifier=''): 117 118 info = set() 118 119 119 if not node :120 if not nodeIdentifier: 120 121 from wokkel import disco 121 122 info.add(disco.DiscoFeature(NS_VERSION)) … … 123 124 return defer.succeed(info) 124 125 125 def getDiscoItems(self, requestor, target, node ):126 def getDiscoItems(self, requestor, target, nodeIdentifier=''): 126 127 return defer.succeed([]) 127 128 -
wokkel/iwokkel.py
r166 r193 8 8 """ 9 9 10 __all__ = ['IXMPPHandler', 'IXMPPHandlerCollection', 11 'IPubSubClient', 'IPubSubService', 'IPubSubResource', 12 'IMUCClient', 'IMUCStatuses'] 10 from __future__ import division, absolute_import 13 11 14 12 from zope.interface import Interface … … 983 981 Return the number of status conditions. 984 982 """ 983 984 985 986 __all__ = ['IXMPPHandler', 'IXMPPHandlerCollection', 987 'IPubSubClient', 'IPubSubService', 'IPubSubResource', 988 'IMUCClient', 'IMUCStatuses'] -
wokkel/muc.py
r166 r219 10 10 U{XEP-0045<http://xmpp.org/extensions/xep-0045.html>}. 11 11 """ 12 13 from __future__ import division, absolute_import 14 12 15 from dateutil.tz import tzutc 13 16 14 from zope.interface import implement s17 from zope.interface import implementer 15 18 16 19 from twisted.internet import defer 20 from twisted.python.compat import unicode 21 from twisted.python.constants import Values, ValueConstant 17 22 from twisted.words.protocols.jabber import jid, error, xmlstream 18 23 from twisted.words.xish import domish 19 24 20 25 from wokkel import data_form, generic, iwokkel, xmppim 21 from wokkel.compat import Values, ValueConstant22 26 from wokkel.delay import Delay, DelayMixin 23 27 from wokkel.subprotocols import XMPPHandler … … 65 69 66 70 71 @implementer(iwokkel.IMUCStatuses) 67 72 class Statuses(set): 68 73 """ … … 72 77 L{STATUS_CODE}. Instances of this class provide L{IMUCStatuses}, that 73 78 defines the supported operations. Even though this class currently derives 74 from C{set}, future versions might not. This provides an upgrade path to79 from L{set}, future versions might not. This provides an upgrade path to 75 80 cater for extensible status conditions, as defined in 76 81 U{XEP-0306<http://xmpp.org/extensions/xep-0306.html>}. 77 82 """ 78 implements(iwokkel.IMUCStatuses)79 83 80 84 … … 225 229 226 230 @param reason: Optional reason for the destruction of this room. 227 @type reason: C{unicode}.231 @type reason: L{unicode}. 228 232 229 233 @param alternate: Optional room JID of an alternate venue. … … 231 235 232 236 @param password: Optional password for entering the alternate venue. 233 @type password: C{unicode}237 @type password: L{unicode} 234 238 """ 235 239 … … 274 278 Render into a domish Element. 275 279 276 @param legacyDelay: If C{True} send the delayed delivery information280 @param legacyDelay: If L{True} send the delayed delivery information 277 281 in legacy format. 278 282 """ … … 324 328 (where the character count is the characters of the complete XML 325 329 stanzas, not only their XML character data). 326 @type maxchars: C{int}330 @type maxchars: L{int} 327 331 328 332 @ivar maxstanzas: Limit the total number of messages in the history to "X". 329 @type mazstanzas: C{int}333 @type mazstanzas: L{int} 330 334 331 335 @ivar seconds: Send only the messages received in the last "X" seconds. 332 @type seconds: C{int}336 @type seconds: L{int} 333 337 334 338 @ivar since: Send only the messages received since the datetime specified. … … 392 396 393 397 @ivar affiliation: Affiliation of the entity to the room. 394 @type affiliation: C{unicode}398 @type affiliation: L{unicode} 395 399 396 400 @ivar role: Role of the entity in the room. 397 @type role: C{unicode}401 @type role: L{unicode} 398 402 399 403 @ivar entity: The real JID of the entity this presence is from. … … 405 409 406 410 @ivar nick: The nick name of the entity in the room. 407 @type nick: C{unicode}411 @type nick: L{unicode} 408 412 """ 409 413 … … 546 550 @param timeout: The number of seconds to wait before the deferred is 547 551 timed out. 548 @type timeout: C{int}552 @type timeout: L{int} 549 553 550 554 The deferred object L{defer.Deferred} is returned. … … 592 596 593 597 @param nick: The nick name for the entitity joining the room. 594 @type nick: C{unicode}598 @type nick: L{unicode} 595 599 596 600 @param historyOptions: Options for conversation history sent by the … … 599 603 600 604 @param password: Optional password for the room. 601 @type password: C{unicode}605 @type password: L{unicode} 602 606 603 607 @return: A deferred that fires when the entity is in the room or an … … 625 629 626 630 @param nick: The new nick name within the room. 627 @type nick: C{unicode}631 @type nick: L{unicode} 628 632 """ 629 633 occupantJID = jid.JID(tuple=(roomJID.user, roomJID.host, nick)) … … 643 647 @param show: The availability of the entity. Common values are xa, 644 648 available, etc 645 @type show: C{unicode}649 @type show: L{unicode} 646 650 647 651 @param status: The current status of the entity. 648 @type status: C{unicode}652 @type status: L{unicode} 649 653 """ 650 654 occupantJID = self._roomOccupantMap[roomJID] … … 701 705 702 706 @param subject: The subject you want to set. 703 @type subject: C{unicode}707 @type subject: L{unicode} 704 708 """ 705 709 message = GroupChat(roomJID.userhostJID(), subject=subject) … … 720 724 721 725 @param reason: The reason for the invite. 722 @type reason: C{unicode}726 @type reason: L{unicode} 723 727 """ 724 728 message = InviteMessage(recipient=roomJID, invitee=invitee, … … 752 756 @type roomJID: L{JID<twisted.words.protocols.jabber.jid.JID>} 753 757 754 @param options: A mapping of field names to values, or C{None} to758 @param options: A mapping of field names to values, or L{None} to 755 759 cancel. 756 @type options: C{dict}760 @type options: L{dict} 757 761 """ 758 762 if options is None: … … 784 788 @param messages: The history to send to the room as an ordered list of 785 789 message, represented by a dictionary with the keys 786 C{'stanza'}, holding the original stanza a787 L{domish.Element}, and C{'timestamp'} with the790 L{'stanza'}, holding the original stanza a 791 L{domish.Element}, and L{'timestamp'} with the 788 792 timestamp. 789 @type messages: C{list} of L{domish.Element}793 @type messages: L{list} of L{domish.Element} 790 794 """ 791 795 … … 819 823 820 824 @return: A deferred that fires with the room's configuration form as 821 a L{data_form.Form} or C{None} if there are no configuration825 a L{data_form.Form} or L{None} if there are no configuration 822 826 options available. 823 827 """ … … 839 843 @type roomJID: L{JID<twisted.words.protocols.jabber.jid.JID>} 840 844 841 @param options: A mapping of field names to values, or C{None} to845 @param options: A mapping of field names to values, or L{None} to 842 846 cancel. 843 @type options: C{dict}847 @type options: L{dict} 844 848 """ 845 849 if options is None: … … 963 967 964 968 @param entities: The list of entities to change for a room. 965 @type entities: C{list} of969 @type entities: L{list} of 966 970 L{JID<twisted.words.protocols.jabber.jid.JID>} 967 971 968 972 @param affiliation: The affilation to the entities will acquire. 969 @type affiliation: C{unicode}973 @type affiliation: L{unicode} 970 974 971 975 @param sender: The entity sending the request. … … 989 993 990 994 @param nick: The nick name for the user in this room. 991 @type nick: C{unicode}995 @type nick: L{unicode} 992 996 993 997 @param reason: The reason for granting voice to the entity. 994 @type reason: C{unicode}998 @type reason: L{unicode} 995 999 996 1000 @param sender: The entity sending the request. … … 1012 1016 1013 1017 @param nick: The nick name for the user in this room. 1014 @type nick: C{unicode}1018 @type nick: L{unicode} 1015 1019 1016 1020 @param reason: The reason for revoking voice from the entity. 1017 @type reason: C{unicode}1021 @type reason: L{unicode} 1018 1022 1019 1023 @param sender: The entity sending the request. … … 1032 1036 1033 1037 @param nick: The nick name for the user in this room. 1034 @type nick: C{unicode}1038 @type nick: L{unicode} 1035 1039 1036 1040 @param reason: The reason for granting moderation to the entity. 1037 @type reason: C{unicode}1041 @type reason: L{unicode} 1038 1042 1039 1043 @param sender: The entity sending the request. … … 1055 1059 1056 1060 @param reason: The reason for banning the entity. 1057 @type reason: C{unicode}1061 @type reason: L{unicode} 1058 1062 1059 1063 @param sender: The entity sending the request. … … 1072 1076 1073 1077 @param nick: The occupant to be banned. 1074 @type nick: C{unicode}1078 @type nick: L{unicode} 1075 1079 1076 1080 @param reason: The reason given for the kick. 1077 @type reason: C{unicode}1081 @type reason: L{unicode} 1078 1082 1079 1083 @param sender: The entity sending the request. … … 1092 1096 1093 1097 @param reason: The reason for the destruction of the room. 1094 @type reason: C{unicode}1098 @type reason: L{unicode} 1095 1099 1096 1100 @param alternate: The JID of the room suggested as an alternate venue. … … 1132 1136 1133 1137 @ivar nick: The nick name for the client in this room. 1134 @type nick: C{unicode}1138 @type nick: L{unicode} 1135 1139 1136 1140 @ivar occupantJID: The JID of the occupant in the room. Generated from … … 1142 1146 L{MUCClientProtocol.getConfiguration} and 1143 1147 L{MUCClientProtocol.configure}. 1144 @type locked: C{bool}1148 @type locked: L{bool} 1145 1149 """ 1146 1150 … … 1187 1191 1188 1192 @param nick: The nick for the user in the MUC room. 1189 @type nick: C{unicode}1193 @type nick: L{unicode} 1190 1194 """ 1191 1195 return self.roster.get(nick) … … 1204 1208 1205 1209 1210 @implementer(IMUCClient) 1206 1211 class MUCClient(MUCClientProtocol): 1207 1212 """ … … 1213 1218 room. Note that a particular entity can only join a room once 1214 1219 at a time. 1215 @type _rooms: C{dict} 1216 """ 1217 1218 implements(IMUCClient) 1220 @type _rooms: L{dict} 1221 """ 1219 1222 1220 1223 def __init__(self, reactor=None): … … 1310 1313 user = User(nick, presence.entity) 1311 1314 1312 # Update user status 1315 # Update user data 1316 user.role = presence.role 1317 user.affiliation = presence.affiliation 1313 1318 user.status = presence.status 1314 1319 user.show = presence.show … … 1400 1405 @type room: L{Room} 1401 1406 1402 @param user: The user that sent the message, or C{None} if it was a1407 @param user: The user that sent the message, or L{None} if it was a 1403 1408 message from the room itself. 1404 1409 @type user: L{User} … … 1421 1426 @type room: L{Room} 1422 1427 1423 @param user: The user that sent the message, or C{None} if it was a1428 @param user: The user that sent the message, or L{None} if it was a 1424 1429 message from the room itself. 1425 1430 @type user: L{User} … … 1440 1445 1441 1446 @param nick: The nick name for the entitity joining the room. 1442 @type nick: C{unicode}1447 @type nick: L{unicode} 1443 1448 1444 1449 @param historyOptions: Options for conversation history sent by the … … 1447 1452 1448 1453 @param password: Optional password for the room. 1449 @type password: C{unicode}1454 @type password: L{unicode} 1450 1455 1451 1456 @return: A deferred that fires with the room when the entity is in the … … 1484 1489 1485 1490 @param nick: The new nick name within the room. 1486 @type nick: C{unicode}1491 @type nick: L{unicode} 1487 1492 """ 1488 1493 def cb(presence): … … 1526 1531 @param show: The availability of the entity. Common values are xa, 1527 1532 available, etc 1528 @type show: C{unicode}1533 @type show: L{unicode} 1529 1534 1530 1535 @param status: The current status of the entity. 1531 @type status: C{unicode}1536 @type status: L{unicode} 1532 1537 """ 1533 1538 room = self._getRoom(roomJID) … … 1545 1550 1546 1551 @param reason: The reason for the destruction of the room. 1547 @type reason: C{unicode}1552 @type reason: L{unicode} 1548 1553 1549 1554 @param alternate: The JID of the room suggested as an alternate venue. -
wokkel/ping.py
r166 r199 11 11 """ 12 12 13 from zope.interface import implements 13 from __future__ import division, absolute_import 14 15 from zope.interface import implementer 14 16 15 17 from twisted.words.protocols.jabber.error import StanzaError … … 57 59 58 60 if sender is not None: 59 request['from'] = unicode(sender)61 request['from'] = sender.full() 60 62 61 63 d = request.send(entity.full()) … … 65 67 66 68 69 @implementer(iwokkel.IDisco) 67 70 class PingHandler(XMPPHandler): 68 71 """ … … 71 74 This handler waits for XMPP Ping requests and sends a response. 72 75 """ 73 74 implements(iwokkel.IDisco)75 76 76 77 def connectionInitialized(self): -
wokkel/pubsub.py
r225 r226 11 11 """ 12 12 13 from zope.interface import implements 13 from __future__ import division, absolute_import 14 15 from zope.interface import implementer 14 16 15 17 from twisted.internet import defer 16 18 from twisted.python import log 19 from twisted.python.compat import StringType, iteritems, unicode 17 20 from twisted.words.protocols.jabber import jid, error 18 21 from twisted.words.xish import domish … … 107 110 108 111 @ivar nodeIdentifier: The identifier of the node subscribed to. The root 109 node is denoted by C{None}.110 @type nodeIdentifier: C{unicode}112 node is denoted by L{None}. 113 @type nodeIdentifier: L{unicode} 111 114 112 115 @ivar subscriber: The subscribing entity. … … 115 118 @ivar state: The subscription state. One of C{'subscribed'}, C{'pending'}, 116 119 C{'unconfigured'}. 117 @type state: C{unicode}120 @type state: L{unicode} 118 121 119 122 @ivar options: Optional list of subscription options. 120 @type options: C{dict}123 @type options: L{dict} 121 124 122 125 @ivar subscriptionIdentifier: Optional subscription identifier. 123 @type subscriptionIdentifier: C{unicode}126 @type subscriptionIdentifier: L{unicode} 124 127 """ 125 128 … … 172 175 """ 173 176 @param id: optional item identifier 174 @type id: C{unicode}177 @type id: L{unicode} 175 178 @param payload: optional item payload. Either as a domish element, or 176 179 as serialized XML. 177 @type payload: object providing L{domish.IElement} or C{unicode}.180 @type payload: object providing L{domish.IElement} or L{unicode}. 178 181 """ 179 182 … … 182 185 self['id'] = id 183 186 if payload is not None: 184 if isinstance(payload, basestring):187 if isinstance(payload, StringType): 185 188 self.addRawXml(payload) 186 189 else: … … 195 198 The set of instance variables used depends on the type of request. If 196 199 a variable is not applicable or not passed in the request, its value is 197 C{None}.200 L{None}. 198 201 199 202 @ivar verb: The type of publish-subscribe request. See C{_requestVerbMap}. 200 @type verb: C{str}.203 @type verb: L{str}. 201 204 202 205 @ivar affiliations: Affiliations to be modified. 203 @type affiliations: C{set}206 @type affiliations: L{set} 204 207 205 208 @ivar items: The items to be published, as L{domish.Element}s. 206 @type items: C{list}209 @type items: L{list} 207 210 208 211 @ivar itemIdentifiers: Identifiers of the items to be retrieved or 209 212 retracted. 210 @type itemIdentifiers: C{set}213 @type itemIdentifiers: L{set} 211 214 212 215 @ivar maxItems: Maximum number of items to retrieve. 213 @type maxItems: C{int}.216 @type maxItems: L{int}. 214 217 215 218 @ivar nodeIdentifier: Identifier of the node the request is about. 216 @type nodeIdentifier: C{unicode}219 @type nodeIdentifier: L{unicode} 217 220 218 221 @ivar nodeType: The type of node that should be created, or for which the 219 222 configuration is retrieved. C{'leaf'} or C{'collection'}. 220 @type nodeType: C{str}223 @type nodeType: L{str} 221 224 222 225 @ivar options: Configurations options for nodes, subscriptions and publish … … 228 231 229 232 @ivar subscriptionIdentifier: Identifier for a specific subscription. 230 @type subscriptionIdentifier: C{unicode}233 @type subscriptionIdentifier: L{unicode} 231 234 232 235 @ivar subscriptions: Subscriptions to be modified, as a set of 233 236 L{Subscription}. 234 @type subscriptions: C{set}237 @type subscriptions: L{set} 235 238 236 239 @ivar affiliations: Affiliations to be modified, as a dictionary of entity 237 240 (L{JID<twisted.words.protocols.jabber.jid.JID>} to affiliation 238 ( C{unicode}).239 @type affiliations: C{dict}241 (L{unicode}). 242 @type affiliations: L{dict} 240 243 """ 241 244 … … 279 282 280 283 # Map request verb to request iq type and subelement name 281 _verbRequestMap = dict(((v, k) for k, v in _requestVerbMap.iteritems()))284 _verbRequestMap = dict(((v, k) for k, v in iteritems(_requestVerbMap))) 282 285 283 286 # Map request verb to parameter handler names … … 667 670 @type recipient: L{wokkel.pubsub.ItemsEvent} 668 671 @param nodeIdentifier: Identifier of the node the event pertains to. 669 @type nodeIdentifier: C{unicode}672 @type nodeIdentifier: L{unicode} 670 673 @param headers: SHIM headers, see L{wokkel.shim.extractHeaders}. 671 @type headers: C{dict}674 @type headers: L{dict} 672 675 """ 673 676 … … 685 688 686 689 @param items: List of received items as domish elements. 687 @type items: C{list} of L{domish.Element}690 @type items: L{list} of L{domish.Element} 688 691 """ 689 692 … … 710 713 711 714 715 @implementer(IPubSubClient) 712 716 class PubSubClient(XMPPHandler): 713 717 """ 714 718 Publish subscribe client protocol. 715 719 """ 716 717 implements(IPubSubClient)718 720 719 721 def connectionInitialized(self): … … 792 794 @type service: L{JID<twisted.words.protocols.jabber.jid.JID>} 793 795 @param nodeIdentifier: Optional suggestion for the id of the node. 794 @type nodeIdentifier: C{unicode}796 @type nodeIdentifier: L{unicode} 795 797 @param options: Optional node configuration options. 796 @type options: C{dict}798 @type options: L{dict} 797 799 """ 798 800 request = PubSubRequest('create') … … 827 829 @type service: L{JID<twisted.words.protocols.jabber.jid.JID>} 828 830 @param nodeIdentifier: The identifier of the node. 829 @type nodeIdentifier: C{unicode}831 @type nodeIdentifier: L{unicode} 830 832 """ 831 833 request = PubSubRequest('delete') … … 845 847 846 848 @param nodeIdentifier: The identifier of the node. 847 @type nodeIdentifier: C{unicode}849 @type nodeIdentifier: L{unicode} 848 850 849 851 @param subscriber: The entity to subscribe to the node. This entity … … 852 854 853 855 @param options: Subscription options. 854 @type options: C{dict}856 @type options: L{dict} 855 857 856 858 @return: Deferred that fires with L{Subscription} or errbacks with … … 897 899 898 900 @param nodeIdentifier: The identifier of the node. 899 @type nodeIdentifier: C{unicode}901 @type nodeIdentifier: L{unicode} 900 902 901 903 @param subscriber: The entity to unsubscribe from the node. … … 903 905 904 906 @param subscriptionIdentifier: Optional subscription identifier. 905 @type subscriptionIdentifier: C{unicode}907 @type subscriptionIdentifier: L{unicode} 906 908 """ 907 909 request = PubSubRequest('unsubscribe') … … 921 923 @type service: L{JID<twisted.words.protocols.jabber.jid.JID>} 922 924 @param nodeIdentifier: The identifier of the node. 923 @type nodeIdentifier: C{unicode}925 @type nodeIdentifier: L{unicode} 924 926 @param items: Optional list of L{Item}s to publish. 925 @type items: C{list}927 @type items: L{list} 926 928 """ 927 929 request = PubSubRequest('publish') … … 934 936 935 937 def items(self, service, nodeIdentifier, maxItems=None, 936 subscriptionIdentifier=None, sender=None ):938 subscriptionIdentifier=None, sender=None, itemIdentifiers=None): 937 939 """ 938 940 Retrieve previously published items from a publish subscribe node. … … 942 944 943 945 @param nodeIdentifier: The identifier of the node. 944 @type nodeIdentifier: C{unicode}946 @type nodeIdentifier: L{unicode} 945 947 946 948 @param maxItems: Optional limit on the number of retrieved items. 947 @type maxItems: C{int}949 @type maxItems: L{int} 948 950 949 951 @param subscriptionIdentifier: Optional subscription identifier. In 950 952 case the node has been subscribed to multiple times, this narrows 951 953 the results to the specific subscription. 952 @type subscriptionIdentifier: C{unicode} 954 @type subscriptionIdentifier: L{unicode} 955 956 @param itemIdentifiers: Identifiers of the items to be retrieved. 957 @type itemIdentifiers: L{set} of L{unicode} 953 958 """ 954 959 request = PubSubRequest('items') … … 959 964 request.subscriptionIdentifier = subscriptionIdentifier 960 965 request.sender = sender 966 request.itemIdentifiers = itemIdentifiers 961 967 962 968 def cb(iq): … … 1001 1007 1002 1008 @param nodeIdentifier: The identifier of the node. 1003 @type nodeIdentifier: C{unicode}1009 @type nodeIdentifier: L{unicode} 1004 1010 1005 1011 @param subscriber: The entity subscribed to the node. … … 1007 1013 1008 1014 @param subscriptionIdentifier: Optional subscription identifier. 1009 @type subscriptionIdentifier: C{unicode}1015 @type subscriptionIdentifier: L{unicode} 1010 1016 1011 1017 @rtype: L{data_form.Form} … … 1038 1044 1039 1045 @param nodeIdentifier: The identifier of the node. 1040 @type nodeIdentifier: C{unicode}1046 @type nodeIdentifier: L{unicode} 1041 1047 1042 1048 @param subscriber: The entity subscribed to the node. … … 1044 1050 1045 1051 @param options: Subscription options. 1046 @type options: C{dict}.1052 @type options: L{dict}. 1047 1053 1048 1054 @param subscriptionIdentifier: Optional subscription identifier. 1049 @type subscriptionIdentifier: C{unicode}1055 @type subscriptionIdentifier: L{unicode} 1050 1056 """ 1051 1057 request = PubSubRequest('optionsSet') … … 1066 1072 1067 1073 1074 @implementer(IPubSubService, disco.IDisco) 1068 1075 class PubSubService(XMPPHandler, IQHandlerMixin): 1069 1076 """ … … 1090 1097 keys C{'category'}, C{'type'} and C{'name'}. 1091 1098 @ivar pubSubFeatures: List of supported publish-subscribe features for 1092 service discovery, as C{str}. 1093 @type pubSubFeatures: C{list} or C{None} 1094 """ 1095 1096 implements(IPubSubService, disco.IDisco) 1099 service discovery, as L{str}. 1100 @type pubSubFeatures: L{list} or L{None} 1101 """ 1097 1102 1098 1103 iqHandlers = { … … 1393 1398 affiliations['node'] = request.nodeIdentifier 1394 1399 1395 for entity, affiliation in result.iteritems():1400 for entity, affiliation in iteritems(result): 1396 1401 item = affiliations.addElement('affiliation') 1397 1402 item['jid'] = entity.full() … … 1504 1509 1505 1510 1511 @implementer(IPubSubResource) 1506 1512 class PubSubResource(object): 1507 1508 implements(IPubSubResource)1509 1513 1510 1514 features = [] -
wokkel/server.py
r184 r206 12 12 """ 13 13 14 # hashlib is new in Python 2.5, try that first. 15 try: 16 from hashlib import sha256 17 digestmod = sha256 18 except ImportError: 19 import Crypto.Hash.SHA256 as digestmod 20 sha256 = digestmod.new 21 14 from __future__ import division, absolute_import 15 16 import binascii 17 from hashlib import sha256 22 18 import hmac 23 19 24 from zope.interface import implement s20 from zope.interface import implementer 25 21 26 22 from twisted.internet import defer, reactor 27 23 from twisted.names.srvconnect import SRVConnector 28 24 from twisted.python import log, randbytes 25 from twisted.python.compat import iteritems, unicode 29 26 from twisted.words.protocols.jabber import error, ijabber, jid, xmlstream 30 27 from twisted.words.xish import domish … … 44 41 @param secret: the shared secret known to the Originating Server and 45 42 Authoritive Server. 46 @type secret: C{str}43 @type secret: L{unicode} 47 44 @param receivingServer: the Receiving Server host name. 48 @type receivingServer: C{str}45 @type receivingServer: L{unicode} 49 46 @param originatingServer: the Originating Server host name. 50 @type originatingServer: C{str}47 @type originatingServer: L{unicode} 51 48 @param streamID: the Stream ID as generated by the Receiving Server. 52 @type streamID: C{str}49 @type streamID: L{unicode} 53 50 @return: hexadecimal digest of the generated key. 54 51 @type: C{str} … … 56 53 57 54 hashObject = sha256() 58 hashObject.update(secret )55 hashObject.update(secret.encode('ascii')) 59 56 hashedSecret = hashObject.hexdigest() 60 57 message = " ".join([receivingServer, originatingServer, streamID]) 61 hash = hmac.HMAC(hashedSecret, message, digestmod=digestmod) 58 hash = hmac.HMAC(hashedSecret.encode('ascii'), 59 message.encode('ascii'), 60 digestmod=sha256) 62 61 return hash.hexdigest() 63 62 … … 78 77 try: 79 78 observer(element) 80 except error.StreamError ,exc:79 except error.StreamError as exc: 81 80 xs.sendStreamError(exc) 82 81 except: … … 108 107 109 108 109 @implementer(ijabber.IInitiatingInitializer) 110 110 class OriginatingDialbackInitializer(object): 111 111 """ 112 112 Server Dialback Initializer for the Orginating Server. 113 113 """ 114 115 implements(ijabber.IInitiatingInitializer)116 114 117 115 _deferred = None … … 161 159 162 160 161 @implementer(ijabber.IInitiatingInitializer) 163 162 class ReceivingDialbackInitializer(object): 164 163 """ 165 164 Server Dialback Initializer for the Receiving Server. 166 165 """ 167 168 implements(ijabber.IInitiatingInitializer)169 166 170 167 _deferred = None … … 329 326 xmlstream.ListenAuthenticator.streamStarted(self, rootElement) 330 327 331 # Compatibility fix for pre-8.2 implementations of ListenAuthenticator332 if not self.xmlstream.sid:333 self.xmlstream.sid = randbytes.secureRandom(8).encode('hex')334 335 328 if self.xmlstream.thisEntity: 336 329 targetDomain = self.xmlstream.thisEntity.host … … 348 341 if xmlstream.NS_STREAMS != rootElement.uri or \ 349 342 self.namespace != self.xmlstream.namespace or \ 350 ('db', NS_DIALBACK) not in rootElement.localPrefixes.iteritems():343 ('db', NS_DIALBACK) not in iteritems(rootElement.localPrefixes): 351 344 raise error.StreamError('invalid-namespace') 352 345 353 346 if targetDomain and targetDomain not in self.service.domains: 354 347 raise error.StreamError('host-unknown') 355 except error.StreamError ,exc:348 except error.StreamError as exc: 356 349 prepareStream(self.service.defaultDomain) 357 350 self.xmlstream.sendStreamError(exc) … … 576 569 self.secret = secret 577 570 else: 578 self.secret = randbytes.secureRandom(16).encode('hex')571 self.secret = binascii.hexlify(randbytes.secureRandom(16)) 579 572 580 573 self._outgoingStreams = {} -
wokkel/shim.py
r165 r201 11 11 """ 12 12 13 from __future__ import division, absolute_import 14 15 from twisted.python.compat import unicode 13 16 from twisted.words.xish import domish 14 17 -
wokkel/subprotocols.py
r166 r194 8 8 """ 9 9 10 __all__ = ['XMPPHandler', 'XMPPHandlerCollection', 'StreamManager', 11 'IQHandlerMixin'] 12 13 from zope.interface import implements 10 from __future__ import division, absolute_import 11 12 from zope.interface import implementer 14 13 15 14 from twisted.internet import defer 16 15 from twisted.internet.error import ConnectionDone 17 16 from twisted.python import failure, log 17 from twisted.python.compat import iteritems, itervalues 18 18 from twisted.python.deprecate import deprecatedModuleAttribute 19 19 from twisted.python.versions import Version … … 31 31 "XMPPHandlerCollection") 32 32 33 @implementer(ijabber.IXMPPHandler) 33 34 class XMPPHandler(object): 34 35 """ … … 38 39 extension protocols, and are referred to as a subprotocol implementation. 39 40 """ 40 41 implements(ijabber.IXMPPHandler)42 41 43 42 def __init__(self): … … 278 277 iqDeferreds = self._iqDeferreds 279 278 self._iqDeferreds = {} 280 for d in i qDeferreds.itervalues():279 for d in itervalues(iqDeferreds): 281 280 d.errback(reason) 282 281 … … 456 455 457 456 handler = None 458 for queryString, method in self.iqHandlers.iteritems():457 for queryString, method in iteritems(self.iqHandlers): 459 458 if xpath.internQuery(queryString).matches(iq): 460 459 handler = getattr(self, method) … … 473 472 474 473 iq.handled = True 474 475 476 477 __all__ = ['XMPPHandler', 'XMPPHandlerCollection', 'StreamManager', 478 'IQHandlerMixin'] -
wokkel/test/helpers.py
r186 r197 6 6 """ 7 7 8 from __future__ import division, absolute_import 9 8 10 from twisted.internet import defer 11 from twisted.python.compat import iteritems 9 12 from twisted.words.xish import xpath 10 13 from twisted.words.xish.utility import EventDispatcher … … 35 38 u'<presence/>' 36 39 >>> def cb(stanza): 37 ... print "Got: %r" stanza.toXml()40 ... print("Got: %r" stanza.toXml()) 38 41 >>> stub.xmlstream.addObserver('/presence') 39 42 >>> stub.send(domish.Element((None, 'presence'))) … … 84 87 handler = None 85 88 iq = parseXml(xml) 86 for queryString, method in self.service.iqHandlers.iteritems():89 for queryString, method in iteritems(self.service.iqHandlers): 87 90 if xpath.internQuery(queryString).matches(iq): 88 91 handler = getattr(self.service, method) -
wokkel/test/test_client.py
r178 r208 5 5 Tests for L{wokkel.client}. 6 6 """ 7 8 from __future__ import division, absolute_import 7 9 8 10 from twisted.internet import defer … … 151 153 def cb(connector): 152 154 self.assertEqual('xmpp-client', connector.service) 153 self.assertIsInstance(connector.domain, bytes) 154 self.assertEqual(b'example.org', connector.domain) 155 self.assertEqual('example.org', connector.domain) 155 156 self.assertEqual(factory, connector.factory) 156 157 -
wokkel/test/test_compat.py
r165 r200 7 7 """ 8 8 9 from zope.interface import implements 9 from __future__ import division, absolute_import 10 11 from zope.interface import implementer 10 12 from twisted.internet import task 11 13 from twisted.internet.interfaces import IReactorTime … … 14 16 15 17 from wokkel.compat import IQ 16 from wokkel.compat import NamedConstant, Names, ValueConstant, Values17 18 18 class DeprecationTest(unittest.TestCase): 19 """ 20 Deprecation tests for L{wokkel.compat}. 21 """ 22 23 def lookForDeprecationWarning(self, testmethod, attributeName, newName): 24 """ 25 Importing C{testmethod} emits a deprecation warning. 26 """ 27 warningsShown = self.flushWarnings([testmethod]) 28 self.assertEqual(len(warningsShown), 1) 29 self.assertIdentical(warningsShown[0]['category'], DeprecationWarning) 30 self.assertEqual( 31 warningsShown[0]['message'], 32 "wokkel.compat." + attributeName + " " 33 "was deprecated in Wokkel 0.7.0: Use " + newName + " instead.") 34 35 36 def test_bootstrapMixinTest(self): 37 """ 38 L{compat.BootstrapMixin} is deprecated. 39 """ 40 from wokkel.compat import BootstrapMixin 41 BootstrapMixin 42 self.lookForDeprecationWarning( 43 self.test_bootstrapMixinTest, 44 "BootstrapMixin", 45 "twisted.words.xish.xmlstream.BootstrapMixin") 46 47 48 def test_xmlStreamServerFactory(self): 49 """ 50 L{compat.XmlStreamServerFactory} is deprecated. 51 """ 52 from wokkel.compat import XmlStreamServerFactory 53 XmlStreamServerFactory 54 self.lookForDeprecationWarning( 55 self.test_xmlStreamServerFactory, 56 "XmlStreamServerFactory", 57 "twisted.words.protocols.jabber.xmlstream." 58 "XmlStreamServerFactory") 59 60 61 19 @implementer(IReactorTime) 62 20 class FakeReactor(object): 63 21 64 implements(IReactorTime)65 22 def __init__(self): 66 23 self.clock = task.Clock() … … 98 55 self.assertFalse(xs.iqDeferreds) 99 56 return d 100 101 102 103 class NamedConstantTests(unittest.TestCase):104 """105 Tests for the L{twisted.python.constants.NamedConstant} class which is used106 to represent individual values.107 """108 def setUp(self):109 """110 Create a dummy container into which constants can be placed.111 """112 class foo(Names):113 pass114 self.container = foo115 116 117 def test_name(self):118 """119 The C{name} attribute of a L{NamedConstant} refers to the value passed120 for the C{name} parameter to C{_realize}.121 """122 name = NamedConstant()123 name._realize(self.container, "bar", None)124 self.assertEqual("bar", name.name)125 126 127 def test_representation(self):128 """129 The string representation of an instance of L{NamedConstant} includes130 the container the instances belongs to as well as the instance's name.131 """132 name = NamedConstant()133 name._realize(self.container, "bar", None)134 self.assertEqual("<foo=bar>", repr(name))135 136 137 def test_equality(self):138 """139 A L{NamedConstant} instance compares equal to itself.140 """141 name = NamedConstant()142 name._realize(self.container, "bar", None)143 self.assertTrue(name == name)144 self.assertFalse(name != name)145 146 147 def test_nonequality(self):148 """149 Two different L{NamedConstant} instances do not compare equal to each150 other.151 """152 first = NamedConstant()153 first._realize(self.container, "bar", None)154 second = NamedConstant()155 second._realize(self.container, "bar", None)156 self.assertFalse(first == second)157 self.assertTrue(first != second)158 159 160 def test_hash(self):161 """162 Because two different L{NamedConstant} instances do not compare as equal163 to each other, they also have different hashes to avoid collisions when164 added to a C{dict} or C{set}.165 """166 first = NamedConstant()167 first._realize(self.container, "bar", None)168 second = NamedConstant()169 second._realize(self.container, "bar", None)170 self.assertNotEqual(hash(first), hash(second))171 172 173 174 class _ConstantsTestsMixin(object):175 """176 Mixin defining test helpers common to multiple types of constants177 collections.178 """179 def _notInstantiableTest(self, name, cls):180 """181 Assert that an attempt to instantiate the constants class raises182 C{TypeError}.183 184 @param name: A C{str} giving the name of the constants collection.185 @param cls: The constants class to test.186 """187 exc = self.assertRaises(TypeError, cls)188 self.assertEqual(name + " may not be instantiated.", str(exc))189 190 191 192 class NamesTests(unittest.TestCase, _ConstantsTestsMixin):193 """194 Tests for L{twisted.python.constants.Names}, a base class for containers of195 related constaints.196 """197 def setUp(self):198 """199 Create a fresh new L{Names} subclass for each unit test to use. Since200 L{Names} is stateful, re-using the same subclass across test methods201 makes exercising all of the implementation code paths difficult.202 """203 class METHOD(Names):204 """205 A container for some named constants to use in unit tests for206 L{Names}.207 """208 GET = NamedConstant()209 PUT = NamedConstant()210 POST = NamedConstant()211 DELETE = NamedConstant()212 213 self.METHOD = METHOD214 215 216 def test_notInstantiable(self):217 """218 A subclass of L{Names} raises C{TypeError} if an attempt is made to219 instantiate it.220 """221 self._notInstantiableTest("METHOD", self.METHOD)222 223 224 def test_symbolicAttributes(self):225 """226 Each name associated with a L{NamedConstant} instance in the definition227 of a L{Names} subclass is available as an attribute on the resulting228 class.229 """230 self.assertTrue(hasattr(self.METHOD, "GET"))231 self.assertTrue(hasattr(self.METHOD, "PUT"))232 self.assertTrue(hasattr(self.METHOD, "POST"))233 self.assertTrue(hasattr(self.METHOD, "DELETE"))234 235 236 def test_withoutOtherAttributes(self):237 """238 As usual, names not defined in the class scope of a L{Names}239 subclass are not available as attributes on the resulting class.240 """241 self.assertFalse(hasattr(self.METHOD, "foo"))242 243 244 def test_representation(self):245 """246 The string representation of a constant on a L{Names} subclass includes247 the name of the L{Names} subclass and the name of the constant itself.248 """249 self.assertEqual("<METHOD=GET>", repr(self.METHOD.GET))250 251 252 def test_lookupByName(self):253 """254 Constants can be looked up by name using L{Names.lookupByName}.255 """256 method = self.METHOD.lookupByName("GET")257 self.assertIdentical(self.METHOD.GET, method)258 259 260 def test_notLookupMissingByName(self):261 """262 Names not defined with a L{NamedConstant} instance cannot be looked up263 using L{Names.lookupByName}.264 """265 self.assertRaises(ValueError, self.METHOD.lookupByName, "lookupByName")266 self.assertRaises(ValueError, self.METHOD.lookupByName, "__init__")267 self.assertRaises(ValueError, self.METHOD.lookupByName, "foo")268 269 270 def test_name(self):271 """272 The C{name} attribute of one of the named constants gives that273 constant's name.274 """275 self.assertEqual("GET", self.METHOD.GET.name)276 277 278 def test_attributeIdentity(self):279 """280 Repeated access of an attribute associated with a L{NamedConstant} value281 in a L{Names} subclass results in the same object.282 """283 self.assertIdentical(self.METHOD.GET, self.METHOD.GET)284 285 286 def test_iterconstants(self):287 """288 L{Names.iterconstants} returns an iterator over all of the constants289 defined in the class, in the order they were defined.290 """291 constants = list(self.METHOD.iterconstants())292 self.assertEqual(293 [self.METHOD.GET, self.METHOD.PUT,294 self.METHOD.POST, self.METHOD.DELETE],295 constants)296 297 298 def test_attributeIterconstantsIdentity(self):299 """300 The constants returned from L{Names.iterconstants} are identical to the301 constants accessible using attributes.302 """303 constants = list(self.METHOD.iterconstants())304 self.assertIdentical(self.METHOD.GET, constants[0])305 self.assertIdentical(self.METHOD.PUT, constants[1])306 self.assertIdentical(self.METHOD.POST, constants[2])307 self.assertIdentical(self.METHOD.DELETE, constants[3])308 309 310 def test_iterconstantsIdentity(self):311 """312 The constants returned from L{Names.iterconstants} are identical on each313 call to that method.314 """315 constants = list(self.METHOD.iterconstants())316 again = list(self.METHOD.iterconstants())317 self.assertIdentical(again[0], constants[0])318 self.assertIdentical(again[1], constants[1])319 self.assertIdentical(again[2], constants[2])320 self.assertIdentical(again[3], constants[3])321 322 323 def test_initializedOnce(self):324 """325 L{Names._enumerants} is initialized once and its value re-used on326 subsequent access.327 """328 first = self.METHOD._enumerants329 self.METHOD.GET # Side-effects!330 second = self.METHOD._enumerants331 self.assertIdentical(first, second)332 333 334 335 class ValuesTests(unittest.TestCase, _ConstantsTestsMixin):336 """337 Tests for L{twisted.python.constants.Names}, a base class for containers of338 related constaints with arbitrary values.339 """340 def setUp(self):341 """342 Create a fresh new L{Values} subclass for each unit test to use. Since343 L{Values} is stateful, re-using the same subclass across test methods344 makes exercising all of the implementation code paths difficult.345 """346 class STATUS(Values):347 OK = ValueConstant("200")348 NOT_FOUND = ValueConstant("404")349 350 self.STATUS = STATUS351 352 353 def test_notInstantiable(self):354 """355 A subclass of L{Values} raises C{TypeError} if an attempt is made to356 instantiate it.357 """358 self._notInstantiableTest("STATUS", self.STATUS)359 360 361 def test_symbolicAttributes(self):362 """363 Each name associated with a L{ValueConstant} instance in the definition364 of a L{Values} subclass is available as an attribute on the resulting365 class.366 """367 self.assertTrue(hasattr(self.STATUS, "OK"))368 self.assertTrue(hasattr(self.STATUS, "NOT_FOUND"))369 370 371 def test_withoutOtherAttributes(self):372 """373 As usual, names not defined in the class scope of a L{Values}374 subclass are not available as attributes on the resulting class.375 """376 self.assertFalse(hasattr(self.STATUS, "foo"))377 378 379 def test_representation(self):380 """381 The string representation of a constant on a L{Values} subclass includes382 the name of the L{Values} subclass and the name of the constant itself.383 """384 self.assertEqual("<STATUS=OK>", repr(self.STATUS.OK))385 386 387 def test_lookupByName(self):388 """389 Constants can be looked up by name using L{Values.lookupByName}.390 """391 method = self.STATUS.lookupByName("OK")392 self.assertIdentical(self.STATUS.OK, method)393 394 395 def test_notLookupMissingByName(self):396 """397 Names not defined with a L{ValueConstant} instance cannot be looked up398 using L{Values.lookupByName}.399 """400 self.assertRaises(ValueError, self.STATUS.lookupByName, "lookupByName")401 self.assertRaises(ValueError, self.STATUS.lookupByName, "__init__")402 self.assertRaises(ValueError, self.STATUS.lookupByName, "foo")403 404 405 def test_lookupByValue(self):406 """407 Constants can be looked up by their associated value, defined by the408 argument passed to L{ValueConstant}, using L{Values.lookupByValue}.409 """410 status = self.STATUS.lookupByValue("200")411 self.assertIdentical(self.STATUS.OK, status)412 413 414 def test_lookupDuplicateByValue(self):415 """416 If more than one constant is associated with a particular value,417 L{Values.lookupByValue} returns whichever of them is defined first.418 """419 class TRANSPORT_MESSAGE(Values):420 """421 Message types supported by an SSH transport.422 """423 KEX_DH_GEX_REQUEST_OLD = ValueConstant(30)424 KEXDH_INIT = ValueConstant(30)425 426 self.assertIdentical(427 TRANSPORT_MESSAGE.lookupByValue(30),428 TRANSPORT_MESSAGE.KEX_DH_GEX_REQUEST_OLD)429 430 431 def test_notLookupMissingByValue(self):432 """433 L{Values.lookupByValue} raises L{ValueError} when called with a value434 with which no constant is associated.435 """436 self.assertRaises(ValueError, self.STATUS.lookupByValue, "OK")437 self.assertRaises(ValueError, self.STATUS.lookupByValue, 200)438 self.assertRaises(ValueError, self.STATUS.lookupByValue, "200.1")439 440 441 def test_name(self):442 """443 The C{name} attribute of one of the constants gives that constant's444 name.445 """446 self.assertEqual("OK", self.STATUS.OK.name)447 448 449 def test_attributeIdentity(self):450 """451 Repeated access of an attribute associated with a L{ValueConstant} value452 in a L{Values} subclass results in the same object.453 """454 self.assertIdentical(self.STATUS.OK, self.STATUS.OK)455 456 457 def test_iterconstants(self):458 """459 L{Values.iterconstants} returns an iterator over all of the constants460 defined in the class, in the order they were defined.461 """462 constants = list(self.STATUS.iterconstants())463 self.assertEqual(464 [self.STATUS.OK, self.STATUS.NOT_FOUND],465 constants)466 467 468 def test_attributeIterconstantsIdentity(self):469 """470 The constants returned from L{Values.iterconstants} are identical to the471 constants accessible using attributes.472 """473 constants = list(self.STATUS.iterconstants())474 self.assertIdentical(self.STATUS.OK, constants[0])475 self.assertIdentical(self.STATUS.NOT_FOUND, constants[1])476 477 478 def test_iterconstantsIdentity(self):479 """480 The constants returned from L{Values.iterconstants} are identical on481 each call to that method.482 """483 constants = list(self.STATUS.iterconstants())484 again = list(self.STATUS.iterconstants())485 self.assertIdentical(again[0], constants[0])486 self.assertIdentical(again[1], constants[1])487 488 489 def test_initializedOnce(self):490 """491 L{Values._enumerants} is initialized once and its value re-used on492 subsequent access.493 """494 first = self.STATUS._enumerants495 self.STATUS.OK # Side-effects!496 second = self.STATUS._enumerants497 self.assertIdentical(first, second) -
wokkel/test/test_component.py
r169 r205 5 5 Tests for L{wokkel.component}. 6 6 """ 7 8 from __future__ import division, absolute_import 7 9 8 10 from zope.interface.verify import verifyObject … … 313 315 Test routing of a message using the default route. 314 316 315 The default route is the one with C{None} as its key in the317 The default route is the one with L{None} as its key in the 316 318 routing table. It is taken when there is no more specific route 317 319 in the routing table that matches the stanza's destination. -
wokkel/test/test_data_form.py
r105 r196 6 6 """ 7 7 8 from __future__ import division, absolute_import 9 8 10 from zope.interface import verify 9 11 from zope.interface.common.mapping import IIterableMapping 10 12 13 from twisted.python.compat import unicode, _PY3 11 14 from twisted.trial import unittest 12 15 from twisted.words.xish import domish … … 1135 1138 form = data_form.Form('submit', fields=fields) 1136 1139 keys = form.keys() 1137 self.assertIsInstance(keys, list) 1140 if not _PY3: 1141 self.assertIsInstance(keys, list) 1138 1142 self.assertEqual(set(['botname', 'public', 'features']), 1139 1143 set(keys)) … … 1148 1152 form = data_form.Form('submit', fields=fields) 1149 1153 values = form.values() 1150 self.assertIsInstance(values, list) 1154 if not _PY3: 1155 self.assertIsInstance(values, list) 1151 1156 self.assertEqual(set(['The Jabber Bot', True]), set(values)) 1152 1157 … … 1160 1165 form = data_form.Form('submit', fields=fields) 1161 1166 items = form.items() 1162 self.assertIsInstance(items, list) 1167 if not _PY3: 1168 self.assertIsInstance(items, list) 1163 1169 self.assertEqual(set([('botname', 'The Jabber Bot'), 1164 1170 ('public', True)]), -
wokkel/test/test_delay.py
r104 r209 5 5 Tests for L{wokkel.delay}. 6 6 """ 7 8 from __future__ import division, absolute_import 7 9 8 10 from datetime import datetime -
wokkel/test/test_disco.py
r103 r198 6 6 """ 7 7 8 from zope.interface import implements 8 from __future__ import division, absolute_import 9 10 from zope.interface import implementer 9 11 10 12 from twisted.internet import defer … … 847 849 ] 848 850 851 @implementer(disco.IDisco) 849 852 class DiscoResponder(XMPPHandler): 850 implements(disco.IDisco)851 853 852 854 def getDiscoInfo(self, requestor, target, nodeIdentifier): … … 874 876 ] 875 877 878 @implementer(disco.IDisco) 876 879 class DiscoResponder(XMPPHandler): 877 implements(disco.IDisco)878 880 879 881 def getDiscoInfo(self, requestor, target, nodeIdentifier): … … 898 900 discoItems = [disco.DiscoItem(JID('example.com'), 'test', 'Test node')] 899 901 902 @implementer(disco.IDisco) 900 903 class DiscoResponder(XMPPHandler): 901 implements(disco.IDisco)902 904 903 905 def getDiscoItems(self, requestor, target, nodeIdentifier): … … 922 924 discoItems = [disco.DiscoItem(JID('example.com'), 'test', 'Test node')] 923 925 926 @implementer(disco.IDisco) 924 927 class DiscoResponder(XMPPHandler): 925 implements(disco.IDisco)926 928 927 929 def getDiscoItems(self, requestor, target, nodeIdentifier): -
wokkel/test/test_generic.py
r185 r195 6 6 """ 7 7 8 from __future__ import division, absolute_import 9 8 10 import re 9 11 12 from zope.interface.verify import verifyObject 13 10 14 from twisted.python import deprecate 15 from twisted.python.compat import unicode 11 16 from twisted.python.versions import Version 12 17 from twisted.trial import unittest … … 16 21 17 22 from wokkel import generic 23 from wokkel.iwokkel import IDisco 18 24 from wokkel.test.helpers import XmlStreamStub 19 25 … … 25 31 """ 26 32 33 def setUp(self): 34 self.protocol = generic.VersionHandler('Test', '0.1.0') 35 36 37 def test_interface(self): 38 """ 39 L{generic.VersionHandler} implements {IDisco}. 40 """ 41 verifyObject(IDisco, self.protocol) 42 43 27 44 def test_onVersion(self): 28 45 """ … … 30 47 """ 31 48 self.stub = XmlStreamStub() 32 self.protocol = generic.VersionHandler('Test', '0.1.0')33 49 self.protocol.xmlstream = self.stub.xmlstream 34 50 self.protocol.send = self.stub.xmlstream.send … … 320 336 self.callDeprecated((Version("Wokkel", 0, 8, 0), 321 337 "unicode.encode('idna')"), 322 generic.prepareIDNName, ( b"example.com"))338 generic.prepareIDNName, ("example.com")) 323 339 test_deprecated.suppress = [] 324 325 326 def test_bytestring(self):327 """328 An ASCII-encoded byte string is left as-is.329 """330 name = b"example.com"331 result = generic.prepareIDNName(name)332 self.assertEqual(b"example.com", result)333 340 334 341 -
wokkel/test/test_iwokkel.py
r165 r193 5 5 Tests for L{wokkel.iwokkel} 6 6 """ 7 8 from __future__ import division, absolute_import 7 9 8 10 from twisted.trial import unittest -
wokkel/test/test_muc.py
r185 r219 6 6 """ 7 7 8 from __future__ import division, absolute_import 9 8 10 from datetime import datetime 9 11 from dateutil.tz import tzutc … … 13 15 from twisted.trial import unittest 14 16 from twisted.internet import defer, task 17 from twisted.python.compat import iteritems, unicode 15 18 from twisted.words.xish import domish, xpath 16 19 from twisted.words.protocols.jabber.jid import JID … … 79 82 } 80 83 81 for code, condition in codes.iteritems():84 for code, condition in iteritems(codes): 82 85 constantName = condition.replace('-', '_').upper() 83 86 self.assertEqual(getattr(muc.STATUS_CODE, constantName), … … 824 827 self.assertNotIdentical(None, nodes, 'Missing query element') 825 828 826 self.assertRaises(StopIteration, n odes[0].elements().next)829 self.assertRaises(StopIteration, next, nodes[0].elements()) 827 830 828 831 xml = u""" … … 970 973 self.assertNotIdentical(None, nodes, 'Missing query element') 971 974 972 self.assertRaises(StopIteration, n odes[0].elements().next)975 self.assertRaises(StopIteration, next, nodes[0].elements()) 973 976 974 977 xml = u""" … … 1491 1494 1492 1495 1496 def test_availableReceivedSetsUserRole(self): 1497 """ 1498 The role received in a presence update is stored on the user. 1499 """ 1500 room = self._createRoom() 1501 user = muc.User(self.nick) 1502 room.addUser(user) 1503 self.assertEquals('none', user.role) 1504 1505 xml = u""" 1506 <presence to='%s' from='%s'> 1507 <x xmlns='http://jabber.org/protocol/muc#user'> 1508 <item affiliation='member' role='participant'/> 1509 </x> 1510 </presence> 1511 """ % (self.userJID, self.occupantJID) 1512 self.stub.send(parseXml(xml)) 1513 1514 self.assertEquals('participant', user.role) 1515 1516 1517 def test_availableReceivedSetsUserAffiliation(self): 1518 """ 1519 The affiliation received in a presence update is stored on the user. 1520 """ 1521 room = self._createRoom() 1522 user = muc.User(self.nick) 1523 room.addUser(user) 1524 self.assertEquals('none', user.affiliation) 1525 1526 xml = u""" 1527 <presence to='%s' from='%s'> 1528 <x xmlns='http://jabber.org/protocol/muc#user'> 1529 <item affiliation='member' role='participant'/> 1530 </x> 1531 </presence> 1532 """ % (self.userJID, self.occupantJID) 1533 self.stub.send(parseXml(xml)) 1534 self.assertEquals('member', user.affiliation) 1535 1536 1493 1537 def test_unavailableReceivedEmptySender(self): 1494 1538 """ -
wokkel/test/test_ping.py
r96 r199 5 5 Tests for L{wokkel.ping}. 6 6 """ 7 8 from __future__ import division, absolute_import 7 9 8 10 from zope.interface import verify -
wokkel/test/test_pubsub.py
r225 r226 5 5 Tests for L{wokkel.pubsub} 6 6 """ 7 8 from __future__ import division, absolute_import 7 9 8 10 from zope.interface import verify … … 113 115 element = subscription.toElement() 114 116 self.assertEqual('1234', element.getAttribute('subid')) 117 118 119 120 class ItemTests(unittest.TestCase): 121 """ 122 Tests for L{pubsub.Item}. 123 """ 124 125 def test_payloadRaw(self): 126 """ 127 Adding a payload as a string assumes serialized XML. 128 """ 129 payload = "<test xmlns='foo'/>" 130 item = pubsub.Item(payload=payload) 131 self.assertEqual(payload, item.children[0]) 132 133 134 def test_payloadElement(self): 135 """ 136 Adding a payload as an domish Element, just adds that element as child. 137 """ 138 payload = domish.Element(('foo', 'test')) 139 item = pubsub.Item(payload=payload) 140 self.assertIs(payload, item.children[0]) 115 141 116 142 … … 802 828 803 829 830 def test_itemsWithItemIdentifiers(self): 831 """ 832 Test sending items request with item identifiers. 833 """ 834 def cb(items): 835 self.assertEquals(2, len(items)) 836 self.assertEquals([item1, item2], items) 837 838 d = self.protocol.items(JID('pubsub.example.org'), 'test', 839 itemIdentifiers=['item1', 'item2']) 840 d.addCallback(cb) 841 842 iq = self.stub.output[-1] 843 self.assertEquals('pubsub.example.org', iq.getAttribute('to')) 844 self.assertEquals('get', iq.getAttribute('type')) 845 self.assertEquals('pubsub', iq.pubsub.name) 846 self.assertEquals(NS_PUBSUB, iq.pubsub.uri) 847 children = list(domish.generateElementsQNamed(iq.pubsub.children, 848 'items', NS_PUBSUB)) 849 self.assertEquals(1, len(children)) 850 child = children[0] 851 self.assertEquals('test', child['node']) 852 itemIdentifiers = [item.getAttribute('id') for item in 853 domish.generateElementsQNamed(child.children, 'item', 854 NS_PUBSUB)] 855 self.assertEquals(['item1', 'item2'], itemIdentifiers) 856 857 response = toResponse(iq, 'result') 858 items = response.addElement((NS_PUBSUB, 'pubsub')).addElement('items') 859 items['node'] = 'test' 860 item1 = items.addElement('item') 861 item1['id'] = 'item1' 862 item2 = items.addElement('item') 863 item2['id'] = 'item2' 864 865 self.stub.send(response) 866 867 return d 868 869 804 870 def test_itemsWithSubscriptionIdentifier(self): 805 871 """ … … 2955 3021 def configureSet(request): 2956 3022 self.assertEquals(['pubsub#deliver_payloads'], 2957 request.options.keys())3023 list(request.options.keys())) 2958 3024 2959 3025 self.resource.getConfigurationOptions = getConfigurationOptions -
wokkel/test/test_server.py
r96 r206 6 6 """ 7 7 8 from __future__ import division, absolute_import 8 9 from twisted.internet import defer 9 10 from twisted.python import failure … … 449 450 450 451 self.assertEqual(1, len(errors)) 452 453 454 def test_generatedSecret(self): 455 self.router = component.Router() 456 self.service = server.ServerService(self.router, 457 domain='example.org') 458 self.assertEqual(32, len(self.service.secret)) -
wokkel/test/test_shim.py
r96 r201 8 8 """ 9 9 10 from __future__ import division, absolute_import 11 12 from twisted.python.compat import unicode 10 13 from twisted.trial import unittest 14 11 15 from wokkel import shim 12 16 from wokkel.generic import parseXml -
wokkel/test/test_subprotocols.py
r165 r194 5 5 Tests for L{wokkel.subprotocols} 6 6 """ 7 8 from __future__ import division, absolute_import 7 9 8 10 from zope.interface.verify import verifyObject … … 211 213 self.xmlstream.connectionMade() 212 214 self.xmlstream.dataReceived( 213 "<stream:stream xmlns='jabber:client' "214 "xmlns:stream='http://etherx.jabber.org/streams' "215 "from='example.com' id='12345'>")215 b"<stream:stream xmlns='jabber:client' " 216 b"xmlns:stream='http://etherx.jabber.org/streams' " 217 b"from='example.com' id='12345'>") 216 218 self.xmlstream.dispatch(self.xmlstream, "//event/stream/authd") 217 219 … … 476 478 xs.transport = proto_helpers.StringTransport() 477 479 xs.connectionMade() 478 xs.dataReceived( "<stream:stream xmlns='jabber:client' "479 "xmlns:stream='http://etherx.jabber.org/streams' "480 "from='example.com' id='12345'>")480 xs.dataReceived(b"<stream:stream xmlns='jabber:client' " 481 b"xmlns:stream='http://etherx.jabber.org/streams' " 482 b"from='example.com' id='12345'>") 481 483 xs.dispatch(xs, "//event/stream/authd") 482 484 sm.send("<presence/>") 483 self.assertEquals( "<presence/>", xs.transport.value())485 self.assertEquals(b"<presence/>", xs.transport.value()) 484 486 485 487 … … 499 501 xs.transport = proto_helpers.StringTransport() 500 502 sm.send("<presence/>") 501 self.assertEquals( "", xs.transport.value())503 self.assertEquals(b"", xs.transport.value()) 502 504 self.assertEquals("<presence/>", sm._packetQueue[0]) 503 505 504 506 xs.connectionMade() 505 self.assertEquals( "", xs.transport.value())507 self.assertEquals(b"", xs.transport.value()) 506 508 self.assertEquals("<presence/>", sm._packetQueue[0]) 507 509 508 xs.dataReceived( "<stream:stream xmlns='jabber:client' "509 "xmlns:stream='http://etherx.jabber.org/streams' "510 "from='example.com' id='12345'>")510 xs.dataReceived(b"<stream:stream xmlns='jabber:client' " 511 b"xmlns:stream='http://etherx.jabber.org/streams' " 512 b"from='example.com' id='12345'>") 511 513 xs.dispatch(xs, "//event/stream/authd") 512 514 513 self.assertEquals( "<presence/>", xs.transport.value())515 self.assertEquals(b"<presence/>", xs.transport.value()) 514 516 self.assertFalse(sm._packetQueue) 515 517 … … 526 528 xs.transport = proto_helpers.StringTransport() 527 529 xs.connectionMade() 528 xs.dataReceived( "<stream:stream xmlns='jabber:client' "529 "xmlns:stream='http://etherx.jabber.org/streams' "530 "from='example.com' id='12345'>")530 xs.dataReceived(b"<stream:stream xmlns='jabber:client' " 531 b"xmlns:stream='http://etherx.jabber.org/streams' " 532 b"from='example.com' id='12345'>") 531 533 sm.send("<presence/>") 532 self.assertEquals( "", xs.transport.value())534 self.assertEquals(b"", xs.transport.value()) 533 535 self.assertEquals("<presence/>", sm._packetQueue[0]) 534 536 … … 552 554 553 555 sm.send("<presence/>") 554 self.assertEquals( "", xs.transport.value())556 self.assertEquals(b"", xs.transport.value()) 555 557 self.assertEquals("<presence/>", sm._packetQueue[0]) 556 558 … … 563 565 564 566 self.streamManager.request(self.request) 565 expected = u"<iq type='get' id='%s'/>" % self.request.stanzaID 566 self.assertEquals(expected, self.transport.value()) 567 self.assertTrue(self.transport.value()) 567 568 568 569 … … 576 577 self.streamManager.request(self.request) 577 578 self.assertNotIdentical(None, self.request.stanzaID) 578 expected = u"<iq type='get' id='%s'/>" % self.request.stanzaID 579 self.assertEquals(expected, self.transport.value()) 579 self.assertTrue(self.transport.value()) 580 580 581 581 … … 588 588 589 589 self.streamManager.request(self.request) 590 expected = u"<iq type='get' id='test'/>"591 590 592 591 xs = self.xmlstream 593 self.assertEquals( "", xs.transport.value())592 self.assertEquals(b"", xs.transport.value()) 594 593 595 594 xs.connectionMade() 596 self.assertEquals( "", xs.transport.value())597 598 xs.dataReceived( "<stream:stream xmlns='jabber:client' "599 "xmlns:stream='http://etherx.jabber.org/streams' "600 "from='example.com' id='12345'>")595 self.assertEquals(b"", xs.transport.value()) 596 597 xs.dataReceived(b"<stream:stream xmlns='jabber:client' " 598 b"xmlns:stream='http://etherx.jabber.org/streams' " 599 b"from='example.com' id='12345'>") 601 600 xs.dispatch(xs, "//event/stream/authd") 602 601 603 self.assert Equals(expected, xs.transport.value())602 self.assertTrue(self.transport.value()) 604 603 self.assertFalse(self.streamManager._packetQueue) 605 604 … … 617 616 618 617 xs = self.xmlstream 619 xs.dataReceived( "<iq type='result' id='test'/>")618 xs.dataReceived(b"<iq type='result' id='test'/>") 620 619 return d 621 620 … … 630 629 631 630 xs = self.xmlstream 632 xs.dataReceived( "<iq type='error' id='test'/>")631 xs.dataReceived(b"<iq type='error' id='test'/>") 633 632 return d 634 633 … … 652 651 653 652 # Receive an untracked iq response 654 self.xmlstream.dataReceived( "<iq type='result' id='other'/>")653 self.xmlstream.dataReceived(b"<iq type='result' id='other'/>") 655 654 self.assertEquals(1, len(dispatched)) 656 655 self.assertFalse(getattr(dispatched[-1], 'handled', False)) … … 666 665 d = self.streamManager.request(self.request) 667 666 xs = self.xmlstream 668 xs.dataReceived( "<iq type='result' id='test'/>")667 xs.dataReceived(b"<iq type='result' id='test'/>") 669 668 self.assertNotIn('test', self.streamManager._iqDeferreds) 670 669 return d … … 722 721 d = self.streamManager.request(self.request) 723 722 self.clock.callLater(1, self.xmlstream.dataReceived, 724 "<iq type='result' id='test'/>")723 b"<iq type='result' id='test'/>") 725 724 self.clock.pump([1, 1]) 726 725 self.assertFalse(self.clock.calls) … … 868 867 self.assertEquals('iq', response.name) 869 868 self.assertEquals('result', response['type']) 870 payload = response.elements().next()869 payload = next(response.elements()) 871 870 self.assertEqual(handler.payload, payload) 872 871 -
wokkel/test/test_xmppim.py
r179 r203 6 6 """ 7 7 8 from __future__ import division, absolute_import 9 8 10 from twisted.internet import defer 9 11 from twisted.trial import unittest 12 from twisted.python.compat import unicode 10 13 from twisted.words.protocols.jabber import error 11 14 from twisted.words.protocols.jabber.jid import JID … … 897 900 element = request.toElement() 898 901 children = element.elements() 899 child = children.next()902 child = next(children) 900 903 self.assertEqual(NS_ROSTER, child.uri) 901 904 self.assertEqual('query', child.name) … … 910 913 element = request.toElement() 911 914 children = element.query.elements() 912 child = children.next()915 child = next(children) 913 916 self.assertEqual(NS_ROSTER, child.uri) 914 917 self.assertEqual('item', child.name) -
wokkel/xmppim.py
r179 r203 11 11 """ 12 12 13 from __future__ import division, absolute_import 14 13 15 import warnings 14 16 15 17 from twisted.internet import defer 18 from twisted.python.compat import iteritems, itervalues, unicode 16 19 from twisted.words.protocols.jabber import error 17 20 from twisted.words.protocols.jabber.jid import JID … … 46 49 47 50 if statuses is not None: 48 for lang, status in statuses.iteritems():51 for lang, status in iteritems(statuses): 49 52 s = self.addElement('status', content=status) 50 53 if lang: … … 59 62 60 63 if statuses is not None: 61 for lang, status in statuses.iteritems():64 for lang, status in iteritems(statuses): 62 65 s = self.addElement('status', content=status) 63 66 if lang: … … 307 310 return self.statuses[None] 308 311 elif self.statuses: 309 for status in self.status.itervalues():312 for status in itervalues(self.status): 310 313 return status 311 314 else: … … 353 356 presence.addElement('priority', content=unicode(self.priority)) 354 357 355 for lang, text in self.statuses.iteritems():358 for lang, text in iteritems(self.statuses): 356 359 status = presence.addElement('status', content=text) 357 360 if lang:
Note: See TracChangeset
for help on using the changeset viewer.