~ntt-pf-lab/nova/monkey_patch_notification

« back to all changes in this revision

Viewing changes to vendor/Twisted-10.0.0/twisted/words/im/basesupport.py

  • Committer: Jesse Andrews
  • Date: 2010-05-28 06:05:26 UTC
  • Revision ID: git-v1:bf6e6e718cdc7488e2da87b21e258ccc065fe499
initial commit

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
 
2
# See LICENSE for details.
 
3
 
 
4
#
 
5
 
 
6
"""Instance Messenger base classes for protocol support.
 
7
 
 
8
You will find these useful if you're adding a new protocol to IM.
 
9
"""
 
10
 
 
11
# Abstract representation of chat "model" classes
 
12
 
 
13
from twisted.words.im.locals import ONLINE, OFFLINE, OfflineError
 
14
from twisted.words.im import interfaces
 
15
 
 
16
from twisted.internet.protocol import Protocol
 
17
 
 
18
from twisted.python.reflect import prefixedMethods
 
19
from twisted.persisted import styles
 
20
 
 
21
from twisted.internet import error
 
22
 
 
23
class AbstractGroup:
 
24
    def __init__(self, name, account):
 
25
        self.name = name
 
26
        self.account = account
 
27
 
 
28
    def getGroupCommands(self):
 
29
        """finds group commands
 
30
 
 
31
        these commands are methods on me that start with imgroup_; they are
 
32
        called with no arguments
 
33
        """
 
34
        return prefixedMethods(self, "imgroup_")
 
35
 
 
36
    def getTargetCommands(self, target):
 
37
        """finds group commands
 
38
 
 
39
        these commands are methods on me that start with imgroup_; they are
 
40
        called with a user present within this room as an argument
 
41
 
 
42
        you may want to override this in your group in order to filter for
 
43
        appropriate commands on the given user
 
44
        """
 
45
        return prefixedMethods(self, "imtarget_")
 
46
 
 
47
    def join(self):
 
48
        if not self.account.client:
 
49
            raise OfflineError
 
50
        self.account.client.joinGroup(self.name)
 
51
 
 
52
    def leave(self):
 
53
        if not self.account.client:
 
54
            raise OfflineError
 
55
        self.account.client.leaveGroup(self.name)
 
56
 
 
57
    def __repr__(self):
 
58
        return '<%s %r>' % (self.__class__, self.name)
 
59
 
 
60
    def __str__(self):
 
61
        return '%s@%s' % (self.name, self.account.accountName)
 
62
 
 
63
class AbstractPerson:
 
64
    def __init__(self, name, baseAccount):
 
65
        self.name = name
 
66
        self.account = baseAccount
 
67
        self.status = OFFLINE
 
68
 
 
69
    def getPersonCommands(self):
 
70
        """finds person commands
 
71
 
 
72
        these commands are methods on me that start with imperson_; they are
 
73
        called with no arguments
 
74
        """
 
75
        return prefixedMethods(self, "imperson_")
 
76
 
 
77
    def getIdleTime(self):
 
78
        """
 
79
        Returns a string.
 
80
        """
 
81
        return '--'
 
82
 
 
83
    def __repr__(self):
 
84
        return '<%s %r/%s>' % (self.__class__, self.name, self.status)
 
85
 
 
86
    def __str__(self):
 
87
        return '%s@%s' % (self.name, self.account.accountName)
 
88
 
 
89
class AbstractClientMixin:
 
90
    """Designed to be mixed in to a Protocol implementing class.
 
91
 
 
92
    Inherit from me first.
 
93
 
 
94
    @ivar _logonDeferred: Fired when I am done logging in.
 
95
    """
 
96
    def __init__(self, account, chatui, logonDeferred):
 
97
        for base in self.__class__.__bases__:
 
98
            if issubclass(base, Protocol):
 
99
                self.__class__._protoBase = base
 
100
                break
 
101
        else:
 
102
            pass
 
103
        self.account = account
 
104
        self.chat = chatui
 
105
        self._logonDeferred = logonDeferred
 
106
 
 
107
    def connectionMade(self):
 
108
        self._protoBase.connectionMade(self)
 
109
 
 
110
    def connectionLost(self, reason):
 
111
        self.account._clientLost(self, reason)
 
112
        self.unregisterAsAccountClient()
 
113
        return self._protoBase.connectionLost(self, reason)
 
114
 
 
115
    def unregisterAsAccountClient(self):
 
116
        """Tell the chat UI that I have `signed off'.
 
117
        """
 
118
        self.chat.unregisterAccountClient(self)
 
119
 
 
120
 
 
121
class AbstractAccount(styles.Versioned):
 
122
    """Base class for Accounts.
 
123
 
 
124
    I am the start of an implementation of L{IAccount<interfaces.IAccount>}, I
 
125
    implement L{isOnline} and most of L{logOn}, though you'll need to implement
 
126
    L{_startLogOn} in a subclass.
 
127
 
 
128
    @cvar _groupFactory: A Callable that will return a L{IGroup} appropriate
 
129
        for this account type.
 
130
    @cvar _personFactory: A Callable that will return a L{IPerson} appropriate
 
131
        for this account type.
 
132
 
 
133
    @type _isConnecting: boolean
 
134
    @ivar _isConnecting: Whether I am in the process of establishing a
 
135
    connection to the server.
 
136
    @type _isOnline: boolean
 
137
    @ivar _isOnline: Whether I am currently on-line with the server.
 
138
 
 
139
    @ivar accountName:
 
140
    @ivar autoLogin:
 
141
    @ivar username:
 
142
    @ivar password:
 
143
    @ivar host:
 
144
    @ivar port:
 
145
    """
 
146
 
 
147
    _isOnline = 0
 
148
    _isConnecting = 0
 
149
    client = None
 
150
 
 
151
    _groupFactory = AbstractGroup
 
152
    _personFactory = AbstractPerson
 
153
 
 
154
    persistanceVersion = 2
 
155
 
 
156
    def __init__(self, accountName, autoLogin, username, password, host, port):
 
157
        self.accountName = accountName
 
158
        self.autoLogin = autoLogin
 
159
        self.username = username
 
160
        self.password = password
 
161
        self.host = host
 
162
        self.port = port
 
163
 
 
164
        self._groups = {}
 
165
        self._persons = {}
 
166
 
 
167
    def upgrateToVersion2(self):
 
168
        # Added in CVS revision 1.16.
 
169
        for k in ('_groups', '_persons'):
 
170
            if not hasattr(self, k):
 
171
                setattr(self, k, {})
 
172
 
 
173
    def __getstate__(self):
 
174
        state = styles.Versioned.__getstate__(self)
 
175
        for k in ('client', '_isOnline', '_isConnecting'):
 
176
            try:
 
177
                del state[k]
 
178
            except KeyError:
 
179
                pass
 
180
        return state
 
181
 
 
182
    def isOnline(self):
 
183
        return self._isOnline
 
184
 
 
185
    def logOn(self, chatui):
 
186
        """Log on to this account.
 
187
 
 
188
        Takes care to not start a connection if a connection is
 
189
        already in progress.  You will need to implement
 
190
        L{_startLogOn} for this to work, and it would be a good idea
 
191
        to override L{_loginFailed} too.
 
192
 
 
193
        @returntype: Deferred L{interfaces.IClient}
 
194
        """
 
195
        if (not self._isConnecting) and (not self._isOnline):
 
196
            self._isConnecting = 1
 
197
            d = self._startLogOn(chatui)
 
198
            d.addCallback(self._cb_logOn)
 
199
            # if chatui is not None:
 
200
            # (I don't particularly like having to pass chatUI to this function,
 
201
            # but we haven't factored it out yet.)
 
202
            d.addCallback(chatui.registerAccountClient)
 
203
            d.addErrback(self._loginFailed)
 
204
            return d
 
205
        else:
 
206
            raise error.ConnectError("Connection in progress")
 
207
 
 
208
    def getGroup(self, name):
 
209
        """Group factory.
 
210
 
 
211
        @param name: Name of the group on this account.
 
212
        @type name: string
 
213
        """
 
214
        group = self._groups.get(name)
 
215
        if group is None:
 
216
            group = self._groupFactory(name, self)
 
217
            self._groups[name] = group
 
218
        return group
 
219
 
 
220
    def getPerson(self, name):
 
221
        """Person factory.
 
222
 
 
223
        @param name: Name of the person on this account.
 
224
        @type name: string
 
225
        """
 
226
        person = self._persons.get(name)
 
227
        if person is None:
 
228
            person = self._personFactory(name, self)
 
229
            self._persons[name] = person
 
230
        return person
 
231
 
 
232
    def _startLogOn(self, chatui):
 
233
        """Start the sign on process.
 
234
 
 
235
        Factored out of L{logOn}.
 
236
 
 
237
        @returntype: Deferred L{interfaces.IClient}
 
238
        """
 
239
        raise NotImplementedError()
 
240
 
 
241
    def _cb_logOn(self, client):
 
242
        self._isConnecting = 0
 
243
        self._isOnline = 1
 
244
        self.client = client
 
245
        return client
 
246
 
 
247
    def _loginFailed(self, reason):
 
248
        """Errorback for L{logOn}.
 
249
 
 
250
        @type reason: Failure
 
251
 
 
252
        @returns: I{reason}, for further processing in the callback chain.
 
253
        @returntype: Failure
 
254
        """
 
255
        self._isConnecting = 0
 
256
        self._isOnline = 0 # just in case
 
257
        return reason
 
258
 
 
259
    def _clientLost(self, client, reason):
 
260
        self.client = None
 
261
        self._isConnecting = 0
 
262
        self._isOnline = 0
 
263
        return reason
 
264
 
 
265
    def __repr__(self):
 
266
        return "<%s: %s (%s@%s:%s)>" % (self.__class__,
 
267
                                        self.accountName,
 
268
                                        self.username,
 
269
                                        self.host,
 
270
                                        self.port)