source:
ralphm-patches/pubsub_resource.patch
@
13:42b22edb29bb
Last change on this file since 13:42b22edb29bb was 13:42b22edb29bb, checked in by Ralph Meijer <ralphm@…>, 13 years ago | |
---|---|
File size: 62.9 KB |
-
wokkel/iwokkel.py
diff -r 29f67459352b wokkel/iwokkel.py
a b 278 278 C{list} of L{domish.Element}) 279 279 """ 280 280 281 281 282 def notifyDelete(service, nodeIdentifier, subscribers, 282 283 redirectURI=None): 283 284 """ … … 526 527 @param nodeIdentifier: The identifier of the node to be delete. 527 528 @type nodeIdentifier: C{unicode} 528 529 """ 530 531 532 533 class IPubSubResource(Interface): 534 535 def locateResource(request): 536 """ 537 Locate a resource that will handle the request. 538 539 @param request: The publish-subscribe request. 540 @type request: L{wokkel.pubsub.PubSubRequest} 541 """ 542 543 544 def getInfo(requestor, service, nodeIdentifier): 545 """ 546 Get node type and meta data. 547 548 @param requestor: The entity the request originated from. 549 @type requestor: L{jid.JID} 550 @param service: The publish-subscribe service entity. 551 @type service: L{jid.JID} 552 @param nodeIdentifier: Identifier of the node to request the info for. 553 @type nodeIdentifier: L{unicode} 554 @return: A deferred that fires with a dictionary. If not empty, 555 it must have the keys C{'type'} and C{'meta-data'} to keep 556 respectively the node type and a dictionary with the meta 557 data for that node. 558 @rtype: L{defer.Deferred} 559 """ 560 561 562 def getNodes(requestor, service, nodeIdentifier): 563 """ 564 Get all nodes contained by this node. 565 566 @param requestor: The entity the request originated from. 567 @type requestor: L{jid.JID} 568 @param service: The publish-subscribe service entity. 569 @type service: L{jid.JID} 570 @param nodeIdentifier: Identifier of the node to request the childs for. 571 @type nodeIdentifier: L{unicode} 572 @return: A deferred that fires with a list of child node identifiers. 573 @rtype: L{defer.Deferred} 574 """ 575 576 577 def getConfigurationOptions(): 578 """ 579 Retrieve all known node configuration options. 580 581 The returned dictionary holds the possible node configuration options 582 by option name. The value of each entry represents the specifics for 583 that option in a dictionary: 584 585 - C{'type'} (C{str}): The option's type (see 586 L{Field<wokkel.data_form.Field>}'s doc string for possible values). 587 - C{'label'} (C{unicode}): A human readable label for this option. 588 - C{'options'} (C{dict}): Optional list of possible values for this 589 option. 590 591 Example:: 592 593 { 594 "pubsub#persist_items": 595 {"type": "boolean", 596 "label": "Persist items to storage"}, 597 "pubsub#deliver_payloads": 598 {"type": "boolean", 599 "label": "Deliver payloads with event notifications"}, 600 "pubsub#send_last_published_item": 601 {"type": "list-single", 602 "label": "When to send the last published item", 603 "options": { 604 "never": "Never", 605 "on_sub": "When a new subscription is processed"} 606 } 607 } 608 609 @rtype: C{dict}. 610 """ 611 612 613 def publish(request): 614 """ 615 Called when a publish request has been received. 616 617 @param request: The publish-subscribe request. 618 @type request: L{wokkel.pubsub.PubSubRequest} 619 @return: deferred that fires on success. 620 @rtype: L{defer.Deferred} 621 """ 622 623 624 def subscribe(request): 625 """ 626 Called when a subscribe request has been received. 627 628 @param request: The publish-subscribe request. 629 @type request: L{wokkel.pubsub.PubSubRequest} 630 @return: A deferred that fires with a 631 L{Subscription<wokkel.pubsub.Subscription>}. 632 @rtype: L{defer.Deferred} 633 """ 634 635 636 def unsubscribe(request): 637 """ 638 Called when a subscribe request has been received. 639 640 @param request: The publish-subscribe request. 641 @type request: L{wokkel.pubsub.PubSubRequest} 642 @return: A deferred that fires with C{None} when unsubscription has 643 succeeded. 644 @rtype: L{defer.Deferred} 645 """ 646 647 648 def subscriptions(request): 649 """ 650 Called when a subscriptions retrieval request has been received. 651 652 @param request: The publish-subscribe request. 653 @type request: L{wokkel.pubsub.PubSubRequest} 654 @return: A deferred that fires with a C{list} of subscriptions as 655 L{Subscription<wokkel.pubsub.Subscription>}. 656 @rtype: L{defer.Deferred} 657 """ 658 659 660 def affiliations(request): 661 """ 662 Called when a affiliations retrieval request has been received. 663 664 @param request: The publish-subscribe request. 665 @type request: L{wokkel.pubsub.PubSubRequest} 666 @return: A deferred that fires with a C{list} of affiliations as 667 C{tuple}s of (node identifier as C{unicode}, affiliation state 668 as C{str}). The affiliation can be C{'owner'}, C{'publisher'}, 669 or C{'outcast'}. 670 @rtype: L{defer.Deferred} 671 """ 672 673 674 def create(request): 675 """ 676 Called when a node creation request has been received. 677 678 @param request: The publish-subscribe request. 679 @type request: L{wokkel.pubsub.PubSubRequest} 680 @return: A deferred that fires with a C{unicode} that represents 681 the identifier of the new node. 682 @rtype: L{defer.Deferred} 683 """ 684 685 686 def default(request): 687 """ 688 Called when a default node configuration request has been received. 689 690 @param request: The publish-subscribe request. 691 @type request: L{wokkel.pubsub.PubSubRequest} 692 @return: A deferred that fires with a C{dict} representing the default 693 node configuration. Keys are C{str}s that represent the 694 field name. Values can be of types C{unicode}, C{int} or 695 C{bool}. 696 @rtype: L{defer.Deferred} 697 """ 698 699 700 def configureGet(request): 701 """ 702 Called when a node configuration retrieval request has been received. 703 704 @param request: The publish-subscribe request. 705 @type request: L{wokkel.pubsub.PubSubRequest} 706 @return: A deferred that fires with a C{dict} representing the node 707 configuration. Keys are C{str}s that represent the field name. 708 Values can be of types C{unicode}, C{int} or C{bool}. 709 @rtype: L{defer.Deferred} 710 """ 711 712 713 def configureSet(request): 714 """ 715 Called when a node configuration change request has been received. 716 717 @param request: The publish-subscribe request. 718 @type request: L{wokkel.pubsub.PubSubRequest} 719 @return: A deferred that fires with C{None} when the node's 720 configuration has been changed. 721 @rtype: L{defer.Deferred} 722 """ 723 724 725 def items(request): 726 """ 727 Called when a items retrieval request has been received. 728 729 @param request: The publish-subscribe request. 730 @type request: L{wokkel.pubsub.PubSubRequest} 731 @return: A deferred that fires with a C{list} of L{pubsub.Item}. 732 @rtype: L{defer.Deferred} 733 """ 734 735 736 def retract(request): 737 """ 738 Called when a item retraction request has been received. 739 740 @param request: The publish-subscribe request. 741 @type request: L{wokkel.pubsub.PubSubRequest} 742 @return: A deferred that fires with C{None} when the given items have 743 been retracted. 744 @rtype: L{defer.Deferred} 745 """ 746 747 748 def purge(request): 749 """ 750 Called when a node purge request has been received. 751 752 @param request: The publish-subscribe request. 753 @type request: L{wokkel.pubsub.PubSubRequest} 754 @return: A deferred that fires with C{None} when the node has been 755 purged. 756 @rtype: L{defer.Deferred} 757 """ 758 759 760 def delete(request): 761 """ 762 Called when a node deletion request has been received. 763 764 @param request: The publish-subscribe request. 765 @type request: L{wokkel.pubsub.PubSubRequest} 766 @return: A deferred that fires with C{None} when the node has been 767 deleted. 768 @rtype: L{defer.Deferred} 769 """ -
wokkel/pubsub.py
diff -r 29f67459352b wokkel/pubsub.py
a b 13 13 from zope.interface import implements 14 14 15 15 from twisted.internet import defer 16 from twisted.python import log 16 17 from twisted.words.protocols.jabber import jid, error, xmlstream 17 18 from twisted.words.xish import domish 18 19 19 20 from wokkel import disco, data_form, generic, shim 20 21 from wokkel.subprotocols import IQHandlerMixin, XMPPHandler 21 from wokkel.iwokkel import IPubSubClient, IPubSubService 22 from wokkel.iwokkel import IPubSubClient, IPubSubService, IPubSubResource 22 23 23 24 # Iq get and set XPath queries 24 25 IQ_GET = '/iq[@type="get"]' … … 84 85 85 86 class Unsupported(PubSubError): 86 87 def __init__(self, feature, text=None): 88 self.feature = feature 87 89 PubSubError.__init__(self, 'feature-not-implemented', 88 90 'unsupported', 89 91 feature, 90 92 text) 91 93 94 def __str__(self): 95 message = PubSubError.__str__(self) 96 message += ', feature %r' % self.feature 97 return message 92 98 93 99 94 100 class Subscription(object): … … 235 241 'retract': ['node', 'itemIdentifiers'], 236 242 'purge': ['node'], 237 243 'delete': ['node'], 238 'affiliationsGet': [ ],244 'affiliationsGet': ['nodeOrEmpty'], 239 245 'affiliationsSet': [], 240 'subscriptionsGet': [ ],246 'subscriptionsGet': ['nodeOrEmpty'], 241 247 'subscriptionsSet': [], 242 248 } 243 249 … … 806 812 '/*': '_onPubSubRequest', 807 813 } 808 814 815 _legacyHandlers = { 816 'publish': ('publish', ['sender', 'recipient', 817 'nodeIdentifier', 'items']), 818 'subscribe': ('subscribe', ['sender', 'recipient', 819 'nodeIdentifier', 'subscriber']), 820 'unsubscribe': ('unsubscribe', ['sender', 'recipient', 821 'nodeIdentifier', 'subscriber']), 822 'subscriptions': ('subscriptions', ['sender', 'recipient']), 823 'affiliations': ('affiliations', ['sender', 'recipient']), 824 'create': ('create', ['sender', 'recipient', 'nodeIdentifier']), 825 'getConfigurationOptions': ('getConfigurationOptions', []), 826 'default': ('getDefaultConfiguration', 827 ['sender', 'recipient', 'nodeType']), 828 'configureGet': ('getConfiguration', ['sender', 'recipient', 829 'nodeIdentifier']), 830 'configureSet': ('setConfiguration', ['sender', 'recipient', 831 'nodeIdentifier', 'options']), 832 'items': ('items', ['sender', 'recipient', 'nodeIdentifier', 833 'maxItems', 'itemIdentifiers']), 834 'retract': ('retract', ['sender', 'recipient', 'nodeIdentifier', 835 'itemIdentifiers']), 836 'purge': ('purge', ['sender', 'recipient', 'nodeIdentifier']), 837 'delete': ('delete', ['sender', 'recipient', 'nodeIdentifier']), 838 } 809 839 810 def __init__(self): 840 hideNodes = False 841 842 def __init__(self, resource=None): 843 self.resource = resource 811 844 self.discoIdentity = {'category': 'pubsub', 812 845 'type': 'generic', 813 846 'name': 'Generic Publish-Subscribe Service'} … … 820 853 821 854 822 855 def getDiscoInfo(self, requestor, target, nodeIdentifier): 823 info = [] 824 825 if not nodeIdentifier: 826 category, idType, name = self.discoIdentity 827 info.append(disco.DiscoIdentity(category, idType, name)) 828 829 info.append(disco.DiscoFeature(disco.NS_DISCO_ITEMS)) 830 info.extend([disco.DiscoFeature("%s#%s" % (NS_PUBSUB, feature)) 831 for feature in self.pubSubFeatures]) 832 833 def toInfo(nodeInfo): 856 def toInfo(nodeInfo, info): 834 857 if not nodeInfo: 835 return 858 return info 836 859 837 860 (nodeType, metaData) = nodeInfo['type'], nodeInfo['meta-data'] 838 861 info.append(disco.DiscoIdentity('pubsub', nodeType)) … … 852 875 853 876 info.append(form) 854 877 855 d = self.getNodeInfo(requestor, target, nodeIdentifier or '') 856 d.addCallback(toInfo) 857 d.addBoth(lambda result: info) 878 return info 879 880 info = [] 881 882 request = PubSubRequest('discoInfo') 883 884 if self.resource is not None: 885 resource = self.resource.locateResource(request) 886 identity = resource.discoIdentity 887 features = resource.features 888 getInfo = resource.getInfo 889 else: 890 category, idType, name = self.discoIdentity 891 identity = disco.DiscoIdentity(category, idType, name) 892 features = self.pubSubFeatures 893 getInfo = self.getNodeInfo 894 895 if not nodeIdentifier: 896 info.append(identity) 897 info.append(disco.DiscoFeature(disco.NS_DISCO_ITEMS)) 898 info.extend([disco.DiscoFeature("%s#%s" % (NS_PUBSUB, feature)) 899 for feature in features]) 900 901 d = getInfo(requestor, target, nodeIdentifier or '') 902 d.addCallback(toInfo, info) 903 d.addErrback(log.err) 858 904 return d 859 905 860 906 861 907 def getDiscoItems(self, requestor, target, nodeIdentifier): 862 if nodeIdentifier or self.hideNodes: 863 return defer.succeed([]) 908 if self.hideNodes: 909 d = defer.succeed([]) 910 elif self.resource is not None: 911 request = PubSubRequest('discoInfo') 912 resource = self.resource.locateResource(request) 913 d = resource.getNodes(requestor, target, nodeIdentifier) 914 elif nodeIdentifier: 915 d = self.getNodes(requestor, target) 916 else: 917 d = defer.succeed([]) 918 864 919 865 d = self.getNodes(requestor, target) 920 866 921 d.addCallback(lambda nodes: [disco.DiscoItem(target, node) 867 922 for node in nodes]) 868 923 return d … … 870 925 871 926 def _onPubSubRequest(self, iq): 872 927 request = PubSubRequest.fromElement(iq) 873 handler = getattr(self, '_on_%s' % request.verb)874 return handler(request)875 928 929 if self.resource is not None: 930 resource = self.resource.locateResource(request) 931 else: 932 resource = self 876 933 877 def _on_publish(self, request): 878 return self.publish(request.sender, request.recipient, 879 request.nodeIdentifier, request.items) 934 # Preprocess the request, knowing the handling resource 935 try: 936 preProcessor = getattr(self, '_preProcess_%s' % request.verb) 937 except AttributeError: 938 pass 939 else: 940 request = preProcessor(resource, request) 941 if request is None: 942 return defer.succeed(None) 880 943 944 # Process the request itself, 945 if resource is not self: 946 try: 947 handler = getattr(resource, request.verb) 948 except AttributeError: 949 # fix lookup feature 950 text = "Request verb: %s" % request.verb 951 return defer.fail(Unsupported('', text)) 881 952 882 def _on_subscribe(self, request): 953 d = handler(request) 954 else: 955 handlerName, argNames = self._legacyHandlers[request.verb] 956 handler = getattr(self, handlerName) 957 args = [getattr(request, arg) for arg in argNames] 958 d = handler(*args) 883 959 884 def toResponse(result): 885 response = domish.Element((NS_PUBSUB, "pubsub")) 886 subscription = response.addElement("subscription") 887 if result.nodeIdentifier: 888 subscription["node"] = result.nodeIdentifier 889 subscription["jid"] = result.subscriber.full() 890 subscription["subscription"] = result.state 891 return response 960 # If needed, translate the result into a response 961 try: 962 cb = getattr(self, '_toResponse_%s' % request.verb) 963 except AttributeError: 964 pass 965 else: 966 d.addCallback(cb, resource, request) 892 967 893 d = self.subscribe(request.sender, request.recipient,894 request.nodeIdentifier, request.subscriber)895 d.addCallback(toResponse)896 968 return d 897 969 898 970 899 def _on_unsubscribe(self, request): 900 return self.unsubscribe(request.sender, request.recipient, 901 request.nodeIdentifier, request.subscriber) 971 def _toResponse_subscribe(self, result, resource, request): 972 response = domish.Element((NS_PUBSUB, "pubsub")) 973 subscription = response.addElement("subscription") 974 if result.nodeIdentifier: 975 subscription["node"] = result.nodeIdentifier 976 subscription["jid"] = result.subscriber.full() 977 subscription["subscription"] = result.state 978 return response 902 979 903 980 904 def _on_optionsGet(self, request): 905 raise Unsupported('subscription-options') 981 def _toResponse_subscriptions(self, result, resource, request): 982 response = domish.Element((NS_PUBSUB, 'pubsub')) 983 subscriptions = response.addElement('subscriptions') 984 for subscription in result: 985 item = subscriptions.addElement('subscription') 986 item['node'] = subscription.nodeIdentifier 987 item['jid'] = subscription.subscriber.full() 988 item['subscription'] = subscription.state 989 return response 906 990 907 991 908 def _on_optionsSet(self, request): 909 raise Unsupported('subscription-options') 992 def _toResponse_affiliations(self, result, resource, request): 993 response = domish.Element((NS_PUBSUB, 'pubsub')) 994 affiliations = response.addElement('affiliations') 910 995 996 for nodeIdentifier, affiliation in result: 997 item = affiliations.addElement('affiliation') 998 item['node'] = nodeIdentifier 999 item['affiliation'] = affiliation 911 1000 912 def _on_subscriptions(self, request):1001 return response 913 1002 914 def toResponse(result): 1003 1004 def _toResponse_create(self, result, resource, request): 1005 if not request.nodeIdentifier or request.nodeIdentifier != result: 915 1006 response = domish.Element((NS_PUBSUB, 'pubsub')) 916 subscriptions = response.addElement('subscriptions') 917 for subscription in result: 918 item = subscriptions.addElement('subscription') 919 item['node'] = subscription.nodeIdentifier 920 item['jid'] = subscription.subscriber.full() 921 item['subscription'] = subscription.state 1007 create = response.addElement('create') 1008 create['node'] = result 922 1009 return response 923 924 d = self.subscriptions(request.sender, request.recipient) 925 d.addCallback(toResponse) 926 return d 927 928 929 def _on_affiliations(self, request): 930 931 def toResponse(result): 932 response = domish.Element((NS_PUBSUB, 'pubsub')) 933 affiliations = response.addElement('affiliations') 934 935 for nodeIdentifier, affiliation in result: 936 item = affiliations.addElement('affiliation') 937 item['node'] = nodeIdentifier 938 item['affiliation'] = affiliation 939 940 return response 941 942 d = self.affiliations(request.sender, request.recipient) 943 d.addCallback(toResponse) 944 return d 945 946 947 def _on_create(self, request): 948 949 def toResponse(result): 950 if not request.nodeIdentifier or request.nodeIdentifier != result: 951 response = domish.Element((NS_PUBSUB, 'pubsub')) 952 create = response.addElement('create') 953 create['node'] = result 954 return response 955 else: 956 return None 957 958 d = self.create(request.sender, request.recipient, 959 request.nodeIdentifier) 960 d.addCallback(toResponse) 961 return d 1010 else: 1011 return None 962 1012 963 1013 964 1014 def _makeFields(self, options, values): … … 977 1027 return fields 978 1028 979 1029 980 def _formFromConfiguration(self, values):981 options = self.getConfigurationOptions()1030 def _formFromConfiguration(self, resource, values): 1031 options = resource.getConfigurationOptions() 982 1032 fields = self._makeFields(options, values) 983 1033 form = data_form.Form(formType="form", 984 1034 formNamespace=NS_PUBSUB_NODE_CONFIG, … … 987 1037 return form 988 1038 989 1039 990 def _checkConfiguration(self, values):991 options = self.getConfigurationOptions()1040 def _checkConfiguration(self, resource, values): 1041 options = resource.getConfigurationOptions() 992 1042 processedValues = {} 993 1043 994 1044 for key, value in values.iteritems(): … … 1012 1062 return processedValues 1013 1063 1014 1064 1015 def _on_default(self, request): 1065 def _preProcess_default(self, resource, request): 1066 if request.nodeType not in ('leaf', 'collection'): 1067 raise error.StanzaError('not-acceptable') 1068 else: 1069 return request 1016 1070 1017 def toResponse(options):1018 response = domish.Element((NS_PUBSUB_OWNER, "pubsub"))1019 default = response.addElement("default")1020 default.addChild(self._formFromConfiguration(options).toElement())1021 return response1022 1071 1023 if request.nodeType not in ('leaf', 'collection'): 1024 return defer.fail(error.StanzaError('not-acceptable')) 1072 def _toResponse_default(self, options, resource, request): 1073 response = domish.Element((NS_PUBSUB_OWNER, "pubsub")) 1074 default = response.addElement("default") 1075 form = self._formFromConfiguration(resource, options) 1076 default.addChild(form.toElement()) 1077 return response 1025 1078 1026 d = self.getDefaultConfiguration(request.sender, request.recipient,1027 request.nodeType)1028 d.addCallback(toResponse)1029 return d1030 1079 1080 def _toResponse_configureGet(self, options, resource, request): 1081 response = domish.Element((NS_PUBSUB_OWNER, "pubsub")) 1082 configure = response.addElement("configure") 1083 form = self._formFromConfiguration(resource, options) 1084 configure.addChild(form.toElement()) 1031 1085 1032 def _on_configureGet(self, request): 1033 def toResponse(options): 1034 response = domish.Element((NS_PUBSUB_OWNER, "pubsub")) 1035 configure = response.addElement("configure") 1036 form = self._formFromConfiguration(options) 1037 configure.addChild(form.toElement()) 1086 if request.nodeIdentifier: 1087 configure["node"] = request.nodeIdentifier 1038 1088 1039 if request.nodeIdentifier: 1040 configure["node"] = request.nodeIdentifier 1089 return response 1041 1090 1042 return response1043 1091 1044 d = self.getConfiguration(request.sender, request.recipient, 1045 request.nodeIdentifier) 1046 d.addCallback(toResponse) 1047 return d 1048 1049 1050 def _on_configureSet(self, request): 1092 def _preProcess_configureSet(self, resource, request): 1051 1093 if request.options: 1052 request.options = self._checkConfiguration(request.options) 1053 return self.setConfiguration(request.sender, request.recipient, 1054 request.nodeIdentifier, 1055 request.options) 1094 request.options = self._checkConfiguration(resource, 1095 request.options) 1096 return request 1056 1097 else: 1057 1098 return None 1058 1099 1059 1100 1101 def _toResponse_items(self, result, resource, request): 1102 response = domish.Element((NS_PUBSUB, 'pubsub')) 1103 items = response.addElement('items') 1104 items["node"] = request.nodeIdentifier 1060 1105 1061 def _on_items(self, request): 1106 for item in result: 1107 items.addChild(item) 1062 1108 1063 def toResponse(result): 1064 response = domish.Element((NS_PUBSUB, 'pubsub')) 1065 items = response.addElement('items') 1066 items["node"] = request.nodeIdentifier 1109 return response 1067 1110 1068 for item in result:1069 items.addChild(item)1070 1071 return response1072 1073 d = self.items(request.sender, request.recipient,1074 request.nodeIdentifier, request.maxItems,1075 request.itemIdentifiers)1076 d.addCallback(toResponse)1077 return d1078 1079 1080 def _on_retract(self, request):1081 return self.retract(request.sender, request.recipient,1082 request.nodeIdentifier, request.itemIdentifiers)1083 1084 1085 def _on_purge(self, request):1086 return self.purge(request.sender, request.recipient,1087 request.nodeIdentifier)1088 1089 1090 def _on_delete(self, request):1091 return self.delete(request.sender, request.recipient,1092 request.nodeIdentifier)1093 1094 1095 def _on_affiliationsGet(self, iq):1096 raise Unsupported('modify-affiliations')1097 1098 1099 def _on_affiliationsSet(self, iq):1100 raise Unsupported('modify-affiliations')1101 1102 1103 def _on_subscriptionsGet(self, iq):1104 raise Unsupported('manage-subscriptions')1105 1106 1107 def _on_subscriptionsSet(self, iq):1108 raise Unsupported('manage-subscriptions')1109 1110 # public methods1111 1111 1112 1112 def _createNotification(self, eventType, service, nodeIdentifier, 1113 1113 subscriber, subscriptions=None): … … 1131 1131 1132 1132 return message 1133 1133 1134 # public methods 1135 1134 1136 def notifyPublish(self, service, nodeIdentifier, notifications): 1135 1137 for subscriber, subscriptions, items in notifications: 1136 1138 message = self._createNotification('items', service, … … 1215 1217 1216 1218 def delete(self, requestor, service, nodeIdentifier): 1217 1219 raise Unsupported('delete-nodes') 1220 1221 1222 1223 class PubSubResource(object): 1224 1225 implements(IPubSubResource) 1226 1227 features = [] 1228 discoIdentity = disco.DiscoIdentity('pubsub', 1229 'service', 1230 'Publish-Subscribe Service') 1231 1232 1233 def locateResource(self, request): 1234 return self 1235 1236 1237 def getInfo(self, requestor, service, nodeIdentifier): 1238 return defer.succeed(None) 1239 1240 1241 def getNodes(self, requestor, service, nodeIdentifier): 1242 return defer.succeed([]) 1243 1244 1245 def getConfigurationOptions(self): 1246 return {} 1247 1248 1249 def publish(self, request): 1250 return defer.fail(Unsupported('publish')) 1251 1252 1253 def subscribe(self, request): 1254 return defer.fail(Unsupported('subscribe')) 1255 1256 1257 def unsubscribe(self, request): 1258 return defer.fail(Unsupported('subscribe')) 1259 1260 1261 def subscriptions(self, request): 1262 return defer.fail(Unsupported('retrieve-subscriptions')) 1263 1264 1265 def affiliations(self, request): 1266 return defer.fail(Unsupported('retrieve-affiliations')) 1267 1268 1269 def create(self, request): 1270 return defer.fail(Unsupported('create-nodes')) 1271 1272 1273 def default(self, request): 1274 return defer.fail(Unsupported('retrieve-default')) 1275 1276 1277 def configureGet(self, request): 1278 return defer.fail(Unsupported('config-node')) 1279 1280 1281 def configureSet(self, request): 1282 return defer.fail(Unsupported('config-node')) 1283 1284 1285 def items(self, request): 1286 return defer.fail(Unsupported('retrieve-items')) 1287 1288 1289 def retract(self, request): 1290 return defer.fail(Unsupported('retract-items')) 1291 1292 1293 def purge(self, request): 1294 return defer.fail(Unsupported('purge-nodes')) 1295 1296 1297 def delete(self, request): 1298 return defer.fail(Unsupported('delete-nodes')) 1299 1300 1301 def affiliationsGet(self, request): 1302 return defer.fail(Unsupported('modify-affiliations')) 1303 1304 1305 def affiliationsSet(self, request): 1306 return defer.fail(Unsupported('modify-affiliations')) 1307 1308 1309 def subscriptionsGet(self, request): 1310 return defer.fail(Unsupported('manage-subscriptions')) 1311 1312 1313 def subscriptionsSet(self, request): 1314 return defer.fail(Unsupported('manage-subscriptions')) -
wokkel/test/test_pubsub.py
diff -r 29f67459352b wokkel/test/test_pubsub.py
a b 1222 1222 1223 1223 def setUp(self): 1224 1224 self.stub = XmlStreamStub() 1225 self.service = pubsub.PubSubService() 1225 self.resource = pubsub.PubSubResource() 1226 self.service = pubsub.PubSubService(self.resource) 1226 1227 self.service.send = self.stub.xmlstream.send 1227 1228 1228 1229 def test_interface(self): … … 1260 1261 Test getDiscoInfo calls getNodeInfo and returns some minimal info. 1261 1262 """ 1262 1263 def cb(info): 1263 self.assertEqual(2, len(info)) 1264 discoInfo = disco.DiscoInfo() 1265 for item in info: 1266 discoInfo.append(item) 1267 self.assertIn(('pubsub', 'service'), discoInfo.identities) 1268 self.assertIn(disco.NS_DISCO_ITEMS, discoInfo.features) 1264 1269 1265 def getNodeInfo(requestor, target, nodeIdentifier):1266 return defer.succeed(None)1267 1268 self.service.getNodeInfo = getNodeInfo1269 1270 d = self.service.getDiscoInfo(JID('user@example.org/home'), 1270 1271 JID('pubsub.example.org'), '') 1271 1272 d.addCallback(cb) … … 1282 1283 discoInfo.append(item) 1283 1284 self.assertIn(('pubsub', 'collection'), discoInfo.identities) 1284 1285 1285 def get NodeInfo(requestor, target, nodeIdentifier):1286 def getInfo(requestor, target, nodeIdentifier): 1286 1287 return defer.succeed({'type': 'collection', 1287 1288 'meta-data': {}}) 1288 1289 1289 self. service.getNodeInfo = getNodeInfo1290 self.resource.getInfo = getInfo 1290 1291 d = self.service.getDiscoInfo(JID('user@example.org/home'), 1291 1292 JID('pubsub.example.org'), '') 1292 1293 d.addCallback(cb) … … 1307 1308 form = discoInfo.extensions[NS_PUBSUB_META_DATA] 1308 1309 self.assertIn('pubsub#node_type', form.fields) 1309 1310 1310 def get NodeInfo(requestor, target, nodeIdentifier):1311 def getInfo(requestor, target, nodeIdentifier): 1311 1312 metaData = [{'var': 'pubsub#persist_items', 1312 1313 'label': 'Persist items to storage', 1313 1314 'value': True}] 1314 1315 return defer.succeed({'type': 'leaf', 'meta-data': metaData}) 1315 1316 1316 self. service.getNodeInfo = getNodeInfo1317 self.resource.getInfo = getInfo 1317 1318 d = self.service.getDiscoInfo(JID('user@example.org/home'), 1318 1319 JID('pubsub.example.org'), '') 1319 1320 d.addCallback(cb) 1320 1321 return d 1321 1322 1322 1323 1323 def test_onPublish(self): 1324 def test_getDiscoInfoResourceFeatures(self): 1325 """ 1326 Test getDiscoInfo with the resource features. 1327 """ 1328 def cb(info): 1329 discoInfo = disco.DiscoInfo() 1330 for item in info: 1331 discoInfo.append(item) 1332 self.assertIn('http://jabber.org/protocol/pubsub#publish', 1333 discoInfo.features) 1334 1335 self.resource.features = ['publish'] 1336 d = self.service.getDiscoInfo(JID('user@example.org/home'), 1337 JID('pubsub.example.org'), '') 1338 d.addCallback(cb) 1339 return d 1340 1341 1342 def test_getDiscoItemsRoot(self): 1343 """ 1344 Test getDiscoItems on the root node. 1345 """ 1346 def getNodes(requestor, service, nodeIdentifier): 1347 return defer.succeed(['node1', 'node2']) 1348 1349 def cb(items): 1350 self.assertEqual(2, len(items)) 1351 item1, item2 = items 1352 1353 self.assertEqual(JID('pubsub.example.org'), item1.entity) 1354 self.assertEqual('node1', item1.nodeIdentifier) 1355 1356 self.assertEqual(JID('pubsub.example.org'), item2.entity) 1357 self.assertEqual('node2', item2.nodeIdentifier) 1358 1359 self.resource.getNodes = getNodes 1360 d = self.service.getDiscoItems(JID('user@example.org/home'), 1361 JID('pubsub.example.org'), 1362 '') 1363 d.addCallback(cb) 1364 return d 1365 1366 1367 def test_getDiscoItemsRootHideNodes(self): 1368 """ 1369 Test getDiscoItems on the root node. 1370 """ 1371 def getNodes(requestor, service, nodeIdentifier): 1372 raise Exception("Unexpected call to getNodes") 1373 1374 def cb(items): 1375 self.assertEqual([], items) 1376 1377 self.service.hideNodes = True 1378 self.resource.getNodes = getNodes 1379 d = self.service.getDiscoItems(JID('user@example.org/home'), 1380 JID('pubsub.example.org'), 1381 '') 1382 d.addCallback(cb) 1383 return d 1384 1385 1386 def test_getDiscoItemsNonRoot(self): 1387 """ 1388 Test getDiscoItems on a non-root node. 1389 """ 1390 def getNodes(requestor, service, nodeIdentifier): 1391 return defer.succeed(['node1', 'node2']) 1392 1393 def cb(items): 1394 self.assertEqual(2, len(items)) 1395 1396 self.resource.getNodes = getNodes 1397 d = self.service.getDiscoItems(JID('user@example.org/home'), 1398 JID('pubsub.example.org'), 1399 'test') 1400 d.addCallback(cb) 1401 return d 1402 1403 1404 def test_on_publish(self): 1324 1405 """ 1325 1406 A publish request should result in L{PubSubService.publish} being 1326 1407 called. … … 1335 1416 </iq> 1336 1417 """ 1337 1418 1338 def publish(request or, service, nodeIdentifier, items):1419 def publish(request): 1339 1420 return defer.succeed(None) 1340 1421 1341 self. service.publish = publish1342 verify.verifyObject(iwokkel.IPubSub Service, self.service)1422 self.resource.publish = publish 1423 verify.verifyObject(iwokkel.IPubSubResource, self.resource) 1343 1424 return self.handleRequest(xml) 1344 1425 1345 1426 1346 def test_on Subscribe(self):1427 def test_on_subscribe(self): 1347 1428 """ 1348 1429 A successful subscription should return the current subscription. 1349 1430 """ … … 1357 1438 </iq> 1358 1439 """ 1359 1440 1360 def subscribe(request or, service, nodeIdentifier, subscriber):1361 return defer.succeed(pubsub.Subscription( nodeIdentifier,1362 subscriber,1441 def subscribe(request): 1442 return defer.succeed(pubsub.Subscription(request.nodeIdentifier, 1443 request.subscriber, 1363 1444 'subscribed')) 1364 1445 1365 1446 def cb(element): … … 1371 1452 self.assertEqual('user@example.org/Home', subscription['jid']) 1372 1453 self.assertEqual('subscribed', subscription['subscription']) 1373 1454 1374 self. service.subscribe = subscribe1375 verify.verifyObject(iwokkel.IPubSub Service, self.service)1455 self.resource.subscribe = subscribe 1456 verify.verifyObject(iwokkel.IPubSubResource, self.resource) 1376 1457 d = self.handleRequest(xml) 1377 1458 d.addCallback(cb) 1378 1459 return d 1379 1460 1380 1461 1381 def test_on SubscribeEmptyNode(self):1462 def test_on_subscribeEmptyNode(self): 1382 1463 """ 1383 1464 A successful subscription on root node should return no node attribute. 1384 1465 """ … … 1392 1473 </iq> 1393 1474 """ 1394 1475 1395 def subscribe(request or, service, nodeIdentifier, subscriber):1396 return defer.succeed(pubsub.Subscription( nodeIdentifier,1397 subscriber,1476 def subscribe(request): 1477 return defer.succeed(pubsub.Subscription(request.nodeIdentifier, 1478 request.subscriber, 1398 1479 'subscribed')) 1399 1480 1400 1481 def cb(element): 1401 1482 self.assertFalse(element.subscription.hasAttribute('node')) 1402 1483 1403 self. service.subscribe = subscribe1404 verify.verifyObject(iwokkel.IPubSub Service, self.service)1484 self.resource.subscribe = subscribe 1485 verify.verifyObject(iwokkel.IPubSubResource, self.resource) 1405 1486 d = self.handleRequest(xml) 1406 1487 d.addCallback(cb) 1407 1488 return d 1408 1489 1409 1490 1410 def test_on Unsubscribe(self):1491 def test_on_unsubscribe(self): 1411 1492 """ 1412 1493 A successful unsubscription should return an empty response. 1413 1494 """ … … 1421 1502 </iq> 1422 1503 """ 1423 1504 1424 def unsubscribe(request or, service, nodeIdentifier, subscriber):1505 def unsubscribe(request): 1425 1506 return defer.succeed(None) 1426 1507 1427 1508 def cb(element): 1428 1509 self.assertIdentical(None, element) 1429 1510 1430 self. service.unsubscribe = unsubscribe1431 verify.verifyObject(iwokkel.IPubSub Service, self.service)1511 self.resource.unsubscribe = unsubscribe 1512 verify.verifyObject(iwokkel.IPubSubResource, self.resource) 1432 1513 d = self.handleRequest(xml) 1433 1514 d.addCallback(cb) 1434 1515 return d 1435 1516 1436 1517 1437 def test_on OptionsGet(self):1518 def test_on_optionsGet(self): 1438 1519 """ 1439 1520 Getting subscription options is not supported. 1440 1521 """ … … 1459 1540 return d 1460 1541 1461 1542 1462 def test_on OptionsSet(self):1543 def test_on_optionsSet(self): 1463 1544 """ 1464 1545 Setting subscription options is not supported. 1465 1546 """ … … 1491 1572 return d 1492 1573 1493 1574 1494 def test_on Subscriptions(self):1575 def test_on_subscriptions(self): 1495 1576 """ 1496 1577 A subscriptions request should result in 1497 1578 L{PubSubService.subscriptions} being called and the result prepared … … 1507 1588 </iq> 1508 1589 """ 1509 1590 1591 def subscriptions(request): 1592 subscription = pubsub.Subscription('test', JID('user@example.org'), 1593 'subscribed') 1594 return defer.succeed([subscription]) 1595 1510 1596 def cb(element): 1511 1597 self.assertEqual('pubsub', element.name) 1512 1598 self.assertEqual(NS_PUBSUB, element.uri) … … 1520 1606 self.assertEqual('test', subscription['node']) 1521 1607 self.assertEqual('subscribed', subscription['subscription']) 1522 1608 1523 1524 def subscriptions(requestor, service): 1525 subscription = pubsub.Subscription('test', JID('user@example.org'), 1526 'subscribed') 1527 return defer.succeed([subscription]) 1528 1529 self.service.subscriptions = subscriptions 1530 verify.verifyObject(iwokkel.IPubSubService, self.service) 1609 self.resource.subscriptions = subscriptions 1610 verify.verifyObject(iwokkel.IPubSubResource, self.resource) 1531 1611 d = self.handleRequest(xml) 1532 1612 d.addCallback(cb) 1533 1613 return d 1534 1614 1535 1615 1536 def test_on Affiliations(self):1616 def test_on_affiliations(self): 1537 1617 """ 1538 1618 A subscriptions request should result in 1539 1619 L{PubSubService.affiliations} being called and the result prepared … … 1549 1629 </iq> 1550 1630 """ 1551 1631 1632 def affiliations(request): 1633 affiliation = ('test', 'owner') 1634 return defer.succeed([affiliation]) 1635 1552 1636 def cb(element): 1553 1637 self.assertEqual('pubsub', element.name) 1554 1638 self.assertEqual(NS_PUBSUB, element.uri) … … 1561 1645 self.assertEqual('test', affiliation['node']) 1562 1646 self.assertEqual('owner', affiliation['affiliation']) 1563 1647 1564 1565 def affiliations(requestor, service): 1566 affiliation = ('test', 'owner') 1567 return defer.succeed([affiliation]) 1568 1569 self.service.affiliations = affiliations 1570 verify.verifyObject(iwokkel.IPubSubService, self.service) 1648 self.resource.affiliations = affiliations 1649 verify.verifyObject(iwokkel.IPubSubResource, self.resource) 1571 1650 d = self.handleRequest(xml) 1572 1651 d.addCallback(cb) 1573 1652 return d 1574 1653 1575 1654 1576 def test_on Create(self):1655 def test_on_create(self): 1577 1656 """ 1578 1657 Replies to create node requests don't return the created node. 1579 1658 """ … … 1587 1666 </iq> 1588 1667 """ 1589 1668 1590 def create(request or, service, nodeIdentifier):1591 return defer.succeed( nodeIdentifier)1669 def create(request): 1670 return defer.succeed(request.nodeIdentifier) 1592 1671 1593 1672 def cb(element): 1594 1673 self.assertIdentical(None, element) 1595 1674 1596 self. service.create = create1597 verify.verifyObject(iwokkel.IPubSub Service, self.service)1675 self.resource.create = create 1676 verify.verifyObject(iwokkel.IPubSubResource, self.resource) 1598 1677 d = self.handleRequest(xml) 1599 1678 d.addCallback(cb) 1600 1679 return d 1601 1680 1602 1681 1603 def test_on CreateChanged(self):1682 def test_on_createChanged(self): 1604 1683 """ 1605 1684 Replies to create node requests return the created node if changed. 1606 1685 """ … … 1614 1693 </iq> 1615 1694 """ 1616 1695 1617 def create(request or, service, nodeIdentifier):1696 def create(request): 1618 1697 return defer.succeed(u'myrenamednode') 1619 1698 1620 1699 def cb(element): … … 1624 1703 self.assertEqual(u'myrenamednode', 1625 1704 element.create.getAttribute('node')) 1626 1705 1627 self. service.create = create1628 verify.verifyObject(iwokkel.IPubSub Service, self.service)1706 self.resource.create = create 1707 verify.verifyObject(iwokkel.IPubSubResource, self.resource) 1629 1708 d = self.handleRequest(xml) 1630 1709 d.addCallback(cb) 1631 1710 return d 1632 1711 1633 1712 1634 def test_on CreateInstant(self):1713 def test_on_createInstant(self): 1635 1714 """ 1636 1715 Replies to create instant node requests return the created node. 1637 1716 """ … … 1645 1724 </iq> 1646 1725 """ 1647 1726 1648 def create(request or, service, nodeIdentifier):1727 def create(request): 1649 1728 return defer.succeed(u'random') 1650 1729 1651 1730 def cb(element): … … 1654 1733 self.assertEqual(NS_PUBSUB, element.create.uri) 1655 1734 self.assertEqual(u'random', element.create.getAttribute('node')) 1656 1735 1657 self. service.create = create1658 verify.verifyObject(iwokkel.IPubSub Service, self.service)1736 self.resource.create = create 1737 verify.verifyObject(iwokkel.IPubSubResource, self.resource) 1659 1738 d = self.handleRequest(xml) 1660 1739 d.addCallback(cb) 1661 1740 return d 1662 1741 1663 1742 1664 def test_on Default(self):1743 def test_on_default(self): 1665 1744 """ 1666 1745 A default request should result in 1667 1746 L{PubSubService.getDefaultConfiguration} being called. … … 1686 1765 "label": "Deliver payloads with event notifications"} 1687 1766 } 1688 1767 1689 def getDefaultConfiguration(requestor, service, nodeType):1768 def default(request): 1690 1769 return defer.succeed({}) 1691 1770 1692 1771 def cb(element): … … 1696 1775 form = data_form.Form.fromElement(element.default.x) 1697 1776 self.assertEqual(NS_PUBSUB_CONFIG, form.formNamespace) 1698 1777 1699 self. service.getConfigurationOptions = getConfigurationOptions1700 self. service.getDefaultConfiguration = getDefaultConfiguration1701 verify.verifyObject(iwokkel.IPubSub Service, self.service)1778 self.resource.getConfigurationOptions = getConfigurationOptions 1779 self.resource.default = default 1780 verify.verifyObject(iwokkel.IPubSubResource, self.resource) 1702 1781 d = self.handleRequest(xml) 1703 1782 d.addCallback(cb) 1704 1783 return d 1705 1784 1706 1785 1707 def test_on DefaultCollection(self):1786 def test_on_defaultCollection(self): 1708 1787 """ 1709 1788 Responses to default requests should depend on passed node type. 1710 1789 """ … … 1735 1814 "label": "Deliver payloads with event notifications"} 1736 1815 } 1737 1816 1738 def getDefaultConfiguration(requestor, service, nodeType):1817 def default(request): 1739 1818 return defer.succeed({}) 1740 1819 1741 self. service.getConfigurationOptions = getConfigurationOptions1742 self. service.getDefaultConfiguration = getDefaultConfiguration1743 verify.verifyObject(iwokkel.IPubSub Service, self.service)1820 self.resource.getConfigurationOptions = getConfigurationOptions 1821 self.resource.default = default 1822 verify.verifyObject(iwokkel.IPubSubResource, self.resource) 1744 1823 return self.handleRequest(xml) 1745 1824 1746 1825 1747 def test_on DefaultUnknownNodeType(self):1826 def test_on_defaultUnknownNodeType(self): 1748 1827 """ 1749 1828 A default request should result in 1750 L{PubSub Service.getDefaultConfiguration} being called.1829 L{PubSubResource.default} being called. 1751 1830 """ 1752 1831 1753 1832 xml = """ … … 1769 1848 </iq> 1770 1849 """ 1771 1850 1772 def getDefaultConfiguration(requestor, service, nodeType):1851 def default(request): 1773 1852 self.fail("Unexpected call to getConfiguration") 1774 1853 1775 1854 def cb(result): 1776 1855 self.assertEquals('not-acceptable', result.condition) 1777 1856 1778 self. service.getDefaultConfiguration = getDefaultConfiguration1779 verify.verifyObject(iwokkel.IPubSub Service, self.service)1857 self.resource.default = default 1858 verify.verifyObject(iwokkel.IPubSubResource, self.resource) 1780 1859 d = self.handleRequest(xml) 1781 1860 self.assertFailure(d, error.StanzaError) 1782 1861 d.addCallback(cb) 1783 1862 return d 1784 1863 1785 1864 1786 def test_on ConfigureGet(self):1865 def test_on_configureGet(self): 1787 1866 """ 1788 On a node configuration get request L{PubSubService.getConfiguration} 1789 is called and results in a data form with the configuration. 1867 On a node configuration get 1868 requestL{PubSubResource.configureGet} is called and results in a 1869 data form with the configuration. 1790 1870 """ 1791 1871 1792 1872 xml = """ … … 1811 1891 "label": "Owner of the node"} 1812 1892 } 1813 1893 1814 def getConfiguration(requestor, service, nodeIdentifier):1894 def configureGet(request): 1815 1895 return defer.succeed({'pubsub#deliver_payloads': '0', 1816 1896 'pubsub#persist_items': '1', 1817 1897 'pubsub#owner': JID('user@example.org'), … … 1845 1925 1846 1926 self.assertNotIn('x-myfield', fields) 1847 1927 1848 1849 self.service.getConfigurationOptions = getConfigurationOptions 1850 self.service.getConfiguration = getConfiguration 1851 verify.verifyObject(iwokkel.IPubSubService, self.service) 1928 self.resource.getConfigurationOptions = getConfigurationOptions 1929 self.resource.configureGet = configureGet 1930 verify.verifyObject(iwokkel.IPubSubResource, self.resource) 1852 1931 d = self.handleRequest(xml) 1853 1932 d.addCallback(cb) 1854 1933 return d 1855 1934 1856 1935 1857 def test_on ConfigureSet(self):1936 def test_on_configureSet(self): 1858 1937 """ 1859 1938 On a node configuration set request the Data Form is parsed and 1860 L{PubSub Service.setConfiguration} is called with the passed options.1939 L{PubSubResource.configureSet} is called with the passed options. 1861 1940 """ 1862 1941 1863 1942 xml = """ … … 1887 1966 "label": "Deliver payloads with event notifications"} 1888 1967 } 1889 1968 1890 def setConfiguration(requestor, service, nodeIdentifier, options):1969 def configureSet(request): 1891 1970 self.assertEqual({'pubsub#deliver_payloads': False, 1892 'pubsub#persist_items': True}, options)1971 'pubsub#persist_items': True}, request.options) 1893 1972 return defer.succeed(None) 1894 1973 1895 self. service.getConfigurationOptions = getConfigurationOptions1896 self. service.setConfiguration = setConfiguration1897 verify.verifyObject(iwokkel.IPubSub Service, self.service)1974 self.resource.getConfigurationOptions = getConfigurationOptions 1975 self.resource.configureSet = configureSet 1976 verify.verifyObject(iwokkel.IPubSubResource, self.resource) 1898 1977 return self.handleRequest(xml) 1899 1978 1900 1979 1901 def test_on ConfigureSetCancel(self):1980 def test_on_configureSetCancel(self): 1902 1981 """ 1903 The node configuration is cancelled, L{PubSubService.setConfiguration}1904 not called.1982 The node configuration is cancelled, 1983 L{PubSubResource.configureSet} not called. 1905 1984 """ 1906 1985 1907 1986 xml = """ … … 1919 1998 </iq> 1920 1999 """ 1921 2000 1922 def setConfiguration(requestor, service, nodeIdentifier, options):2001 def configureSet(request): 1923 2002 self.fail("Unexpected call to setConfiguration") 1924 2003 1925 self. service.setConfiguration = setConfiguration1926 verify.verifyObject(iwokkel.IPubSub Service, self.service)2004 self.resource.configureSet = configureSet 2005 verify.verifyObject(iwokkel.IPubSubResource, self.resource) 1927 2006 return self.handleRequest(xml) 1928 2007 1929 2008 1930 def test_on ConfigureSetIgnoreUnknown(self):2009 def test_on_configureSetIgnoreUnknown(self): 1931 2010 """ 1932 2011 On a node configuration set request unknown fields should be ignored. 1933 2012 """ … … 1959 2038 "label": "Deliver payloads with event notifications"} 1960 2039 } 1961 2040 1962 def setConfiguration(requestor, service, nodeIdentifier, options): 1963 self.assertEquals(['pubsub#deliver_payloads'], options.keys()) 2041 def configureSet(request): 2042 self.assertEquals(['pubsub#deliver_payloads'], 2043 request.options.keys()) 1964 2044 1965 self. service.getConfigurationOptions = getConfigurationOptions1966 self. service.setConfiguration = setConfiguration1967 verify.verifyObject(iwokkel.IPubSub Service, self.service)2045 self.resource.getConfigurationOptions = getConfigurationOptions 2046 self.resource.configureSet = configureSet 2047 verify.verifyObject(iwokkel.IPubSubResource, self.resource) 1968 2048 return self.handleRequest(xml) 1969 2049 1970 2050 1971 def test_on ConfigureSetBadFormType(self):2051 def test_on_configureSetBadFormType(self): 1972 2052 """ 1973 2053 On a node configuration set request unknown fields should be ignored. 1974 2054 """ … … 1999 2079 return d 2000 2080 2001 2081 2002 def test_on Items(self):2082 def test_on_items(self): 2003 2083 """ 2004 2084 On a items request, return all items for the given node. 2005 2085 """ … … 2012 2092 </iq> 2013 2093 """ 2014 2094 2015 def items(requestor, service, nodeIdentifier, maxItems, 2016 itemIdentifiers): 2095 def items(request): 2017 2096 return defer.succeed([pubsub.Item('current')]) 2018 2097 2019 2098 def cb(element): … … 2026 2105 self.assertEqual(NS_PUBSUB, item.uri) 2027 2106 self.assertEqual('current', item['id']) 2028 2107 2029 self.service.items = items 2108 self.resource.items = items 2109 verify.verifyObject(iwokkel.IPubSubResource, self.resource) 2030 2110 d = self.handleRequest(xml) 2031 2111 d.addCallback(cb) 2032 2112 return d 2033 2113 2034 2114 2035 def test_on Retract(self):2115 def test_on_retract(self): 2036 2116 """ 2037 A retract request should result in L{PubSub Service.retract} being2038 called.2117 A retract request should result in L{PubSubResource.retract} 2118 being called. 2039 2119 """ 2040 2120 2041 2121 xml = """ … … 2050 2130 </iq> 2051 2131 """ 2052 2132 2053 def retract(request or, service, nodeIdentifier, itemIdentifiers):2133 def retract(request): 2054 2134 return defer.succeed(None) 2055 2135 2056 self.service.retract = retract 2136 self.resource.retract = retract 2137 verify.verifyObject(iwokkel.IPubSubResource, self.resource) 2057 2138 return self.handleRequest(xml) 2058 2139 2059 2140 2060 def test_on Purge(self):2141 def test_on_purge(self): 2061 2142 """ 2062 A purge request should result in L{PubSub Service.purge} being2143 A purge request should result in L{PubSubResource.purge} being 2063 2144 called. 2064 2145 """ 2065 2146 … … 2072 2153 </iq> 2073 2154 """ 2074 2155 2075 def purge(request or, service, nodeIdentifier):2156 def purge(request): 2076 2157 return defer.succeed(None) 2077 2158 2078 self.service.purge = purge 2159 self.resource.purge = purge 2160 verify.verifyObject(iwokkel.IPubSubResource, self.resource) 2079 2161 return self.handleRequest(xml) 2080 2162 2081 2163 2082 def test_on Delete(self):2164 def test_on_delete(self): 2083 2165 """ 2084 A delete request should result in L{PubSub Service.delete} being2166 A delete request should result in L{PubSubResource.delete} being 2085 2167 called. 2086 2168 """ 2087 2169 … … 2094 2176 </iq> 2095 2177 """ 2096 2178 2097 def delete(request or, service, nodeIdentifier):2179 def delete(request): 2098 2180 return defer.succeed(None) 2099 2181 2100 self.service.delete = delete 2182 self.resource.delete = delete 2183 verify.verifyObject(iwokkel.IPubSubResource, self.resource) 2101 2184 return self.handleRequest(xml) 2102 2185 2103 2186 … … 2148 2231 self.assertEqual(redirectURI, message.event.delete.redirect['uri']) 2149 2232 2150 2233 2151 def test_on SubscriptionsGet(self):2234 def test_on_subscriptionsGet(self): 2152 2235 """ 2153 2236 Getting subscription options is not supported. 2154 2237 """ … … 2175 2258 return d 2176 2259 2177 2260 2178 def test_on SubscriptionsSet(self):2261 def test_on_subscriptionsSet(self): 2179 2262 """ 2180 2263 Setting subscription options is not supported. 2181 2264 """ … … 2202 2285 return d 2203 2286 2204 2287 2205 def test_on AffiliationsGet(self):2288 def test_on_affiliationsGet(self): 2206 2289 """ 2207 2290 Getting subscription options is not supported. 2208 2291 """ … … 2229 2312 return d 2230 2313 2231 2314 2232 def test_on AffiliationsSet(self):2315 def test_on_affiliationsSet(self): 2233 2316 """ 2234 2317 Setting subscription options is not supported. 2235 2318 """ … … 2256 2339 return d 2257 2340 2258 2341 2342 2343 class PubSubServiceWithoutResourceTest(unittest.TestCase, TestableRequestHandlerMixin): 2344 2345 def setUp(self): 2346 self.stub = XmlStreamStub() 2347 self.service = pubsub.PubSubService() 2348 self.service.send = self.stub.xmlstream.send 2349 2350 2259 2351 def test_publish(self): 2260 2352 """ 2261 2353 Non-overridden L{PubSubService.publish} yields unsupported error. … … 2604 2696 self.assertFailure(d, error.StanzaError) 2605 2697 d.addCallback(cb) 2606 2698 return d 2699 2700 2701 2702 class PubSubResourceTest(unittest.TestCase): 2703 2704 def setUp(self): 2705 self.resource = pubsub.PubSubResource() 2706 2707 2708 def test_interface(self): 2709 """ 2710 Do instances of L{pubsub.PubSubResource} provide L{iwokkel.IPubSubResource}? 2711 """ 2712 verify.verifyObject(iwokkel.IPubSubResource, self.resource) 2713 2714 2715 def test_getNodes(self): 2716 """ 2717 Default getNodes returns an empty list. 2718 """ 2719 def cb(nodes): 2720 self.assertEquals([], nodes) 2721 2722 d = self.resource.getNodes(JID('user@example.org/home'), 2723 JID('pubsub.example.org'), 2724 '') 2725 d.addCallback(cb) 2726 return d 2727 2728 2729 def test_publish(self): 2730 """ 2731 Non-overridden L{PubSubResource.publish} yields unsupported 2732 error. 2733 """ 2734 2735 def cb(result): 2736 self.assertEquals('feature-not-implemented', result.condition) 2737 self.assertEquals('unsupported', result.appCondition.name) 2738 self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri) 2739 self.assertEquals('publish', result.appCondition['feature']) 2740 2741 d = self.resource.publish(pubsub.PubSubRequest()) 2742 self.assertFailure(d, error.StanzaError) 2743 d.addCallback(cb) 2744 return d 2745 2746 2747 def test_subscribe(self): 2748 """ 2749 Non-overridden subscriptions yields unsupported error. 2750 """ 2751 2752 def cb(result): 2753 self.assertEquals('feature-not-implemented', result.condition) 2754 self.assertEquals('unsupported', result.appCondition.name) 2755 self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri) 2756 self.assertEquals('subscribe', result.appCondition['feature']) 2757 2758 d = self.resource.subscribe(pubsub.PubSubRequest()) 2759 self.assertFailure(d, error.StanzaError) 2760 d.addCallback(cb) 2761 return d 2762 2763 2764 def test_unsubscribe(self): 2765 """ 2766 Non-overridden unsubscribe yields unsupported error. 2767 """ 2768 2769 def cb(result): 2770 self.assertEquals('feature-not-implemented', result.condition) 2771 self.assertEquals('unsupported', result.appCondition.name) 2772 self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri) 2773 self.assertEquals('subscribe', result.appCondition['feature']) 2774 2775 d = self.resource.unsubscribe(pubsub.PubSubRequest()) 2776 self.assertFailure(d, error.StanzaError) 2777 d.addCallback(cb) 2778 return d 2779 2780 2781 def test_subscriptions(self): 2782 """ 2783 Non-overridden subscriptions yields unsupported error. 2784 """ 2785 2786 def cb(result): 2787 self.assertEquals('feature-not-implemented', result.condition) 2788 self.assertEquals('unsupported', result.appCondition.name) 2789 self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri) 2790 self.assertEquals('retrieve-subscriptions', 2791 result.appCondition['feature']) 2792 2793 d = self.resource.subscriptions(pubsub.PubSubRequest()) 2794 self.assertFailure(d, error.StanzaError) 2795 d.addCallback(cb) 2796 return d 2797 2798 2799 def test_affiliations(self): 2800 """ 2801 Non-overridden affiliations yields unsupported error. 2802 """ 2803 2804 def cb(result): 2805 self.assertEquals('feature-not-implemented', result.condition) 2806 self.assertEquals('unsupported', result.appCondition.name) 2807 self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri) 2808 self.assertEquals('retrieve-affiliations', 2809 result.appCondition['feature']) 2810 2811 d = self.resource.affiliations(pubsub.PubSubRequest()) 2812 self.assertFailure(d, error.StanzaError) 2813 d.addCallback(cb) 2814 return d 2815 2816 2817 def test_create(self): 2818 """ 2819 Non-overridden create yields unsupported error. 2820 """ 2821 2822 def cb(result): 2823 self.assertEquals('feature-not-implemented', result.condition) 2824 self.assertEquals('unsupported', result.appCondition.name) 2825 self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri) 2826 self.assertEquals('create-nodes', result.appCondition['feature']) 2827 2828 d = self.resource.create(pubsub.PubSubRequest()) 2829 self.assertFailure(d, error.StanzaError) 2830 d.addCallback(cb) 2831 return d 2832 2833 2834 def test_default(self): 2835 """ 2836 Non-overridden default yields unsupported error. 2837 """ 2838 2839 def cb(result): 2840 self.assertEquals('feature-not-implemented', result.condition) 2841 self.assertEquals('unsupported', result.appCondition.name) 2842 self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri) 2843 self.assertEquals('retrieve-default', 2844 result.appCondition['feature']) 2845 2846 d = self.resource.default(pubsub.PubSubRequest()) 2847 self.assertFailure(d, error.StanzaError) 2848 d.addCallback(cb) 2849 return d 2850 2851 2852 def test_configureGet(self): 2853 """ 2854 Non-overridden configureGet yields unsupported 2855 error. 2856 """ 2857 2858 def cb(result): 2859 self.assertEquals('feature-not-implemented', result.condition) 2860 self.assertEquals('unsupported', result.appCondition.name) 2861 self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri) 2862 self.assertEquals('config-node', result.appCondition['feature']) 2863 2864 d = self.resource.configureGet(pubsub.PubSubRequest()) 2865 self.assertFailure(d, error.StanzaError) 2866 d.addCallback(cb) 2867 return d 2868 2869 2870 def test_configureSet(self): 2871 """ 2872 Non-overridden configureSet yields unsupported error. 2873 """ 2874 2875 def cb(result): 2876 self.assertEquals('feature-not-implemented', result.condition) 2877 self.assertEquals('unsupported', result.appCondition.name) 2878 self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri) 2879 self.assertEquals('config-node', result.appCondition['feature']) 2880 2881 d = self.resource.configureSet(pubsub.PubSubRequest()) 2882 self.assertFailure(d, error.StanzaError) 2883 d.addCallback(cb) 2884 return d 2885 2886 2887 def test_items(self): 2888 """ 2889 Non-overridden items yields unsupported error. 2890 """ 2891 2892 def cb(result): 2893 self.assertEquals('feature-not-implemented', result.condition) 2894 self.assertEquals('unsupported', result.appCondition.name) 2895 self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri) 2896 self.assertEquals('retrieve-items', result.appCondition['feature']) 2897 2898 d = self.resource.items(pubsub.PubSubRequest()) 2899 self.assertFailure(d, error.StanzaError) 2900 d.addCallback(cb) 2901 return d 2902 2903 2904 def test_retract(self): 2905 """ 2906 Non-overridden retract yields unsupported error. 2907 """ 2908 2909 def cb(result): 2910 self.assertEquals('feature-not-implemented', result.condition) 2911 self.assertEquals('unsupported', result.appCondition.name) 2912 self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri) 2913 self.assertEquals('retract-items', result.appCondition['feature']) 2914 2915 d = self.resource.retract(pubsub.PubSubRequest()) 2916 self.assertFailure(d, error.StanzaError) 2917 d.addCallback(cb) 2918 return d 2919 2920 2921 def test_purge(self): 2922 """ 2923 Non-overridden purge yields unsupported error. 2924 """ 2925 2926 def cb(result): 2927 self.assertEquals('feature-not-implemented', result.condition) 2928 self.assertEquals('unsupported', result.appCondition.name) 2929 self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri) 2930 self.assertEquals('purge-nodes', result.appCondition['feature']) 2931 2932 d = self.resource.purge(pubsub.PubSubRequest()) 2933 self.assertFailure(d, error.StanzaError) 2934 d.addCallback(cb) 2935 return d 2936 2937 2938 def test_delete(self): 2939 """ 2940 Non-overridden delete yields unsupported error. 2941 """ 2942 2943 def cb(result): 2944 self.assertEquals('feature-not-implemented', result.condition) 2945 self.assertEquals('unsupported', result.appCondition.name) 2946 self.assertEquals(NS_PUBSUB_ERRORS, result.appCondition.uri) 2947 self.assertEquals('delete-nodes', result.appCondition['feature']) 2948 2949 d = self.resource.delete(pubsub.PubSubRequest()) 2950 self.assertFailure(d, error.StanzaError) 2951 d.addCallback(cb) 2952 return d
Note: See TracBrowser
for help on using the repository browser.