comparison src/server/server.py @ 451:1a0cec9b0f1e

better PEP-8 compliance
author souliane <souliane@mailoo.org>
date Tue, 20 May 2014 10:54:03 +0200
parents 981ed669d3b3
children da2a7f2b34c9
comparison
equal deleted inserted replaced
450:41aae13cab2b 451:1a0cec9b0f1e
65 jid = Attribute("JID associated with the profile") 65 jid = Attribute("JID associated with the profile")
66 66
67 67
68 class SATSession(object): 68 class SATSession(object):
69 implements(ISATSession) 69 implements(ISATSession)
70
70 def __init__(self, session): 71 def __init__(self, session):
71 self.profile = None 72 self.profile = None
72 self.jid = None 73 self.jid = None
73 74
74 75
91 92
92 def touch(self): 93 def touch(self):
93 if not self.__lock: 94 if not self.__lock:
94 server.Session.touch(self) 95 server.Session.touch(self)
95 96
97
96 class ProtectedFile(File): 98 class ProtectedFile(File):
97 """A File class which doens't show directory listing""" 99 """A File class which doens't show directory listing"""
98 100
99 def directoryListing(self): 101 def directoryListing(self):
100 return NoResource() 102 return NoResource()
101 103
104
102 class SATActionIDHandler(object): 105 class SATActionIDHandler(object):
103 """Manage SàT action action_id lifecycle""" 106 """Manage SàT action action_id lifecycle"""
104 ID_LIFETIME = 30 #after this time (in seconds), action_id will be suppressed and action result will be ignored 107 ID_LIFETIME = 30 # after this time (in seconds), action_id will be suppressed and action result will be ignored
105 108
106 def __init__(self): 109 def __init__(self):
107 self.waiting_ids = {} 110 self.waiting_ids = {}
108 111
109 def waitForId(self, callback, action_id, profile, *args, **kwargs): 112 def waitForId(self, callback, action_id, profile, *args, **kwargs):
118 reactor.callLater(self.ID_LIFETIME, self.purgeID, action_tuple) 121 reactor.callLater(self.ID_LIFETIME, self.purgeID, action_tuple)
119 122
120 def purgeID(self, action_tuple): 123 def purgeID(self, action_tuple):
121 """Called when an action_id has not be handled in time""" 124 """Called when an action_id has not be handled in time"""
122 if action_tuple in self.waiting_ids: 125 if action_tuple in self.waiting_ids:
123 log.warning ("action of action_id %s [%s] has not been managed, action_id is now ignored" % action_tuple) 126 log.warning("action of action_id %s [%s] has not been managed, action_id is now ignored" % action_tuple)
124 del self.waiting_ids[action_tuple] 127 del self.waiting_ids[action_tuple]
125 128
126 def actionResultCb(self, answer_type, action_id, data, profile): 129 def actionResultCb(self, answer_type, action_id, data, profile):
127 """Manage the actionResult signal""" 130 """Manage the actionResult signal"""
128 action_tuple = (action_id, profile) 131 action_tuple = (action_id, profile)
129 if action_tuple in self.waiting_ids: 132 if action_tuple in self.waiting_ids:
130 callback, args, kwargs = self.waiting_ids[action_tuple] 133 callback, args, kwargs = self.waiting_ids[action_tuple]
131 del self.waiting_ids[action_tuple] 134 del self.waiting_ids[action_tuple]
132 callback(answer_type, action_id, data, *args, **kwargs) 135 callback(answer_type, action_id, data, *args, **kwargs)
133 136
137
134 class JSONRPCMethodManager(jsonrpc.JSONRPC): 138 class JSONRPCMethodManager(jsonrpc.JSONRPC):
135 139
136 def __init__(self, sat_host): 140 def __init__(self, sat_host):
137 jsonrpc.JSONRPC.__init__(self) 141 jsonrpc.JSONRPC.__init__(self)
138 self.sat_host=sat_host 142 self.sat_host = sat_host
139 143
140 def asyncBridgeCall(self, method_name, *args, **kwargs): 144 def asyncBridgeCall(self, method_name, *args, **kwargs):
141 """Call an asynchrone bridge method and return a deferred 145 """Call an asynchrone bridge method and return a deferred
142 @param method_name: name of the method as a unicode 146 @param method_name: name of the method as a unicode
143 @return: a deferred which trigger the result 147 @return: a deferred which trigger the result
172 self.session = request.getSession() 176 self.session = request.getSession()
173 profile = ISATSession(self.session).profile 177 profile = ISATSession(self.session).profile
174 if not profile: 178 if not profile:
175 #user is not identified, we return a jsonrpc fault 179 #user is not identified, we return a jsonrpc fault
176 parsed = jsonrpclib.loads(request.content.read()) 180 parsed = jsonrpclib.loads(request.content.read())
177 fault = jsonrpclib.Fault(C.ERRNUM_LIBERVIA, "Not allowed") #FIXME: define some standard error codes for libervia 181 fault = jsonrpclib.Fault(C.ERRNUM_LIBERVIA, "Not allowed") # FIXME: define some standard error codes for libervia
178 return jsonrpc.JSONRPC._cbRender(self, fault, request, parsed.get('id'), parsed.get('jsonrpc')) 182 return jsonrpc.JSONRPC._cbRender(self, fault, request, parsed.get('id'), parsed.get('jsonrpc'))
179 return jsonrpc.JSONRPC.render(self, request) 183 return jsonrpc.JSONRPC.render(self, request)
180 184
181 def jsonrpc_getProfileJid(self): 185 def jsonrpc_getProfileJid(self):
182 """Return the jid of the profile""" 186 """Return the jid of the profile"""
230 @param presence: value from ("", "chat", "away", "dnd", "xa") 234 @param presence: value from ("", "chat", "away", "dnd", "xa")
231 @param status: any string to describe your status 235 @param status: any string to describe your status
232 """ 236 """
233 profile = ISATSession(self.session).profile 237 profile = ISATSession(self.session).profile
234 self.sat_host.bridge.setPresence('', presence, {'': status}, profile) 238 self.sat_host.bridge.setPresence('', presence, {'': status}, profile)
235
236 239
237 def jsonrpc_sendMessage(self, to_jid, msg, subject, type_, options={}): 240 def jsonrpc_sendMessage(self, to_jid, msg, subject, type_, options={}):
238 """send message""" 241 """send message"""
239 profile = ISATSession(self.session).profile 242 profile = ISATSession(self.session).profile
240 return self.asyncBridgeCall("sendMessage", to_jid, msg, subject, type_, options, profile) 243 return self.asyncBridgeCall("sendMessage", to_jid, msg, subject, type_, options, profile)
340 @param node: comments node 343 @param node: comments node
341 """ 344 """
342 profile = ISATSession(self.session).profile 345 profile = ISATSession(self.session).profile
343 d = self.asyncBridgeCall("getGroupBlogComments", service, node, profile) 346 d = self.asyncBridgeCall("getGroupBlogComments", service, node, profile)
344 return d 347 return d
345
346 348
347 def jsonrpc_getPresenceStatuses(self): 349 def jsonrpc_getPresenceStatuses(self):
348 """Get Presence information for connected contacts""" 350 """Get Presence information for connected contacts"""
349 profile = ISATSession(self.session).profile 351 profile = ISATSession(self.session).profile
350 return self.sat_host.bridge.getPresenceStatuses(profile) 352 return self.sat_host.bridge.getPresenceStatuses(profile)
359 return {} 361 return {}
360 if JID(from_jid).userhost() != sat_jid.userhost() and JID(to_jid).userhost() != sat_jid.userhost(): 362 if JID(from_jid).userhost() != sat_jid.userhost() and JID(to_jid).userhost() != sat_jid.userhost():
361 log.error("Trying to get history from a different jid, maybe a hack attempt ?") 363 log.error("Trying to get history from a different jid, maybe a hack attempt ?")
362 return {} 364 return {}
363 d = self.asyncBridgeCall("getHistory", from_jid, to_jid, size, between, profile) 365 d = self.asyncBridgeCall("getHistory", from_jid, to_jid, size, between, profile)
366
364 def show(result_dbus): 367 def show(result_dbus):
365 result = [] 368 result = []
366 for line in result_dbus: 369 for line in result_dbus:
367 #XXX: we have to do this stupid thing because Python D-Bus use its own types instead of standard types 370 #XXX: we have to do this stupid thing because Python D-Bus use its own types instead of standard types
368 # and txJsonRPC doesn't accept D-Bus types, resulting in a empty query 371 # and txJsonRPC doesn't accept D-Bus types, resulting in a empty query
427 self.sat_host.bridge.tarotGameLaunch(other_players, room_jid, profile) 430 self.sat_host.bridge.tarotGameLaunch(other_players, room_jid, profile)
428 431
429 def jsonrpc_getTarotCardsPaths(self): 432 def jsonrpc_getTarotCardsPaths(self):
430 """Give the path of all the tarot cards""" 433 """Give the path of all the tarot cards"""
431 _join = os.path.join 434 _join = os.path.join
432 _media_dir = _join(self.sat_host.media_dir,'') 435 _media_dir = _join(self.sat_host.media_dir, '')
433 return map(lambda x: _join(C.MEDIA_DIR, x[len(_media_dir):]), glob.glob(_join(_media_dir, C.CARDS_DIR, '*_*.png'))); 436 return map(lambda x: _join(C.MEDIA_DIR, x[len(_media_dir):]), glob.glob(_join(_media_dir, C.CARDS_DIR, '*_*.png')))
434 437
435 def jsonrpc_tarotGameReady(self, player, referee): 438 def jsonrpc_tarotGameReady(self, player, referee):
436 """Tell to the server that we are ready to start the game""" 439 """Tell to the server that we are ready to start the game"""
437 profile = ISATSession(self.session).profile 440 profile = ISATSession(self.session).profile
438 self.sat_host.bridge.tarotGameReady(player, referee, profile) 441 self.sat_host.bridge.tarotGameReady(player, referee, profile)
552 """This class manage the registration procedure with SàT 555 """This class manage the registration procedure with SàT
553 It provide an api for the browser, check password and setup the web server""" 556 It provide an api for the browser, check password and setup the web server"""
554 557
555 def __init__(self, sat_host): 558 def __init__(self, sat_host):
556 JSONRPCMethodManager.__init__(self, sat_host) 559 JSONRPCMethodManager.__init__(self, sat_host)
557 self.profiles_waiting={} 560 self.profiles_waiting = {}
558 self.request=None 561 self.request = None
559 562
560 def getWaitingRequest(self, profile): 563 def getWaitingRequest(self, profile):
561 """Tell if a profile is trying to log in""" 564 """Tell if a profile is trying to log in"""
562 if self.profiles_waiting.has_key(profile): 565 if profile in self.profiles_waiting:
563 return self.profiles_waiting[profile] 566 return self.profiles_waiting[profile]
564 else: 567 else:
565 return None 568 return None
566 569
567 def render(self, request): 570 def render(self, request):
579 if method not in ['isRegistered', 'registerParams', 'getMenus']: 582 if method not in ['isRegistered', 'registerParams', 'getMenus']:
580 #if we don't call these methods, we need to be identified 583 #if we don't call these methods, we need to be identified
581 profile = ISATSession(_session).profile 584 profile = ISATSession(_session).profile
582 if not profile: 585 if not profile:
583 #user is not identified, we return a jsonrpc fault 586 #user is not identified, we return a jsonrpc fault
584 fault = jsonrpclib.Fault(C.ERRNUM_LIBERVIA, "Not allowed") #FIXME: define some standard error codes for libervia 587 fault = jsonrpclib.Fault(C.ERRNUM_LIBERVIA, "Not allowed") # FIXME: define some standard error codes for libervia
585 return jsonrpc.JSONRPC._cbRender(self, fault, request, parsed.get('id'), parsed.get('jsonrpc')) 588 return jsonrpc.JSONRPC._cbRender(self, fault, request, parsed.get('id'), parsed.get('jsonrpc'))
586 self.request = request 589 self.request = request
587 return jsonrpc.JSONRPC.render(self, request) 590 return jsonrpc.JSONRPC.render(self, request)
588 591
589 def loginOrRegister(self, request): 592 def loginOrRegister(self, request):
741 return self.sat_host.bridge.isConnected(profile) 744 return self.sat_host.bridge.isConnected(profile)
742 745
743 def jsonrpc_connect(self): 746 def jsonrpc_connect(self):
744 _session = self.request.getSession() 747 _session = self.request.getSession()
745 profile = ISATSession(_session).profile 748 profile = ISATSession(_session).profile
746 if self.profiles_waiting.has_key(profile): 749 if profile in self.profiles_waiting:
747 raise jsonrpclib.Fault(1,'Already waiting') #FIXME: define some standard error codes for libervia 750 raise jsonrpclib.Fault(1, 'Already waiting') # FIXME: define some standard error codes for libervia
748 self.profiles_waiting[profile] = self.request 751 self.profiles_waiting[profile] = self.request
749 self.sat_host.bridge.connect(profile) 752 self.sat_host.bridge.connect(profile)
750 return server.NOT_DONE_YET 753 return server.NOT_DONE_YET
751 754
752 def jsonrpc_isRegistered(self): 755 def jsonrpc_isRegistered(self):
799 802
800 class SignalHandler(jsonrpc.JSONRPC): 803 class SignalHandler(jsonrpc.JSONRPC):
801 804
802 def __init__(self, sat_host): 805 def __init__(self, sat_host):
803 Resource.__init__(self) 806 Resource.__init__(self)
804 self.register=None 807 self.register = None
805 self.sat_host=sat_host 808 self.sat_host = sat_host
806 self.signalDeferred = {} 809 self.signalDeferred = {}
807 self.queue = {} 810 self.queue = {}
808 811
809 def plugRegister(self, register): 812 def plugRegister(self, register):
810 self.register = register 813 self.register = register
812 def jsonrpc_getSignals(self): 815 def jsonrpc_getSignals(self):
813 """Keep the connection alive until a signal is received, then send it 816 """Keep the connection alive until a signal is received, then send it
814 @return: (signal, *signal_args)""" 817 @return: (signal, *signal_args)"""
815 _session = self.request.getSession() 818 _session = self.request.getSession()
816 profile = ISATSession(_session).profile 819 profile = ISATSession(_session).profile
817 if profile in self.queue: #if we have signals to send in queue 820 if profile in self.queue: # if we have signals to send in queue
818 if self.queue[profile]: 821 if self.queue[profile]:
819 return self.queue[profile].pop(0) 822 return self.queue[profile].pop(0)
820 else: 823 else:
821 #the queue is empty, we delete the profile from queue 824 #the queue is empty, we delete the profile from queue
822 del self.queue[profile] 825 del self.queue[profile]
823 _session.lock() #we don't want the session to expire as long as this connection is active 826 _session.lock() # we don't want the session to expire as long as this connection is active
827
824 def unlock(signal, profile): 828 def unlock(signal, profile):
825 _session.unlock() 829 _session.unlock()
826 try: 830 try:
827 source_defer = self.signalDeferred[profile] 831 source_defer = self.signalDeferred[profile]
828 if source_defer.called and source_defer.result[0] == "disconnected": 832 if source_defer.called and source_defer.result[0] == "disconnected":
844 return 848 return
845 if profile in self.signalDeferred: 849 if profile in self.signalDeferred:
846 self.signalDeferred[profile].callback((function_name,args[:-1])) 850 self.signalDeferred[profile].callback((function_name,args[:-1]))
847 del self.signalDeferred[profile] 851 del self.signalDeferred[profile]
848 else: 852 else:
849 if not self.queue.has_key(profile): 853 if profile not in self.queue:
850 self.queue[profile] = [] 854 self.queue[profile] = []
851 self.queue[profile].append((function_name, args[:-1])) 855 self.queue[profile].append((function_name, args[:-1]))
852 return genericCb 856 return genericCb
853 857
854 def connected(self, profile): 858 def connected(self, profile):
864 self.sat_host.prof_connected.remove(profile) 868 self.sat_host.prof_connected.remove(profile)
865 if profile in self.signalDeferred: 869 if profile in self.signalDeferred:
866 self.signalDeferred[profile].callback(("disconnected",)) 870 self.signalDeferred[profile].callback(("disconnected",))
867 del self.signalDeferred[profile] 871 del self.signalDeferred[profile]
868 else: 872 else:
869 if not self.queue.has_key(profile): 873 if profile not in self.queue:
870 self.queue[profile] = [] 874 self.queue[profile] = []
871 self.queue[profile].append(("disconnected",)) 875 self.queue[profile].append(("disconnected",))
872 876
873
874 def connectionError(self, error_type, profile): 877 def connectionError(self, error_type, profile):
875 assert(self.register) #register must be plugged 878 assert(self.register) # register must be plugged
876 request = self.register.getWaitingRequest(profile) 879 request = self.register.getWaitingRequest(profile)
877 if request: #The user is trying to log in 880 if request: # The user is trying to log in
878 if error_type == "AUTH_ERROR": 881 if error_type == "AUTH_ERROR":
879 _error_t = "AUTH ERROR" 882 _error_t = "AUTH ERROR"
880 else: 883 else:
881 _error_t = "UNKNOWN" 884 _error_t = "UNKNOWN"
882 self.register._logginError(profile, request, _error_t) 885 self.register._logginError(profile, request, _error_t)
888 _session = request.getSession() 891 _session = request.getSession()
889 parsed = jsonrpclib.loads(request.content.read()) 892 parsed = jsonrpclib.loads(request.content.read())
890 profile = ISATSession(_session).profile 893 profile = ISATSession(_session).profile
891 if not profile: 894 if not profile:
892 #user is not identified, we return a jsonrpc fault 895 #user is not identified, we return a jsonrpc fault
893 fault = jsonrpclib.Fault(C.ERRNUM_LIBERVIA, "Not allowed") #FIXME: define some standard error codes for libervia 896 fault = jsonrpclib.Fault(C.ERRNUM_LIBERVIA, "Not allowed") # FIXME: define some standard error codes for libervia
894 return jsonrpc.JSONRPC._cbRender(self, fault, request, parsed.get('id'), parsed.get('jsonrpc')) 897 return jsonrpc.JSONRPC._cbRender(self, fault, request, parsed.get('id'), parsed.get('jsonrpc'))
895 self.request = request 898 self.request = request
896 return jsonrpc.JSONRPC.render(self, request) 899 return jsonrpc.JSONRPC.render(self, request)
900
897 901
898 class UploadManager(Resource): 902 class UploadManager(Resource):
899 """This class manage the upload of a file 903 """This class manage the upload of a file
900 It redirect the stream to SàT core backend""" 904 It redirect the stream to SàT core backend"""
901 isLeaf = True 905 isLeaf = True
902 NAME = 'path' #name use by the FileUpload 906 NAME = 'path' # name use by the FileUpload
903 907
904 def __init__(self, sat_host): 908 def __init__(self, sat_host):
905 self.sat_host=sat_host 909 self.sat_host = sat_host
906 self.upload_dir = tempfile.mkdtemp() 910 self.upload_dir = tempfile.mkdtemp()
907 self.sat_host.addCleanup(shutil.rmtree, self.upload_dir) 911 self.sat_host.addCleanup(shutil.rmtree, self.upload_dir)
908 912
909 def getTmpDir(self): 913 def getTmpDir(self):
910 return self.upload_dir 914 return self.upload_dir
934 #FIXME: the uploaded file is fully loaded in memory at form parsing time so far 938 #FIXME: the uploaded file is fully loaded in memory at form parsing time so far
935 # (see twisted.web.http.Request.requestReceived). A custom requestReceived should 939 # (see twisted.web.http.Request.requestReceived). A custom requestReceived should
936 # be written in the futur. In addition, it is not yet possible to get progression informations 940 # be written in the futur. In addition, it is not yet possible to get progression informations
937 # (see http://twistedmatrix.com/trac/ticket/288) 941 # (see http://twistedmatrix.com/trac/ticket/288)
938 942
939 with open(filepath,'w') as f: 943 with open(filepath, 'w') as f:
940 f.write(request.args[self.NAME][0]) 944 f.write(request.args[self.NAME][0])
941 945
942 def finish(d): 946 def finish(d):
943 error = isinstance(d, Exception) or isinstance (d, Failure) 947 error = isinstance(d, Exception) or isinstance(d, Failure)
944 request.write('KO' if error else 'OK') 948 request.write('KO' if error else 'OK')
945 # TODO: would be great to re-use the original Exception class and message 949 # TODO: would be great to re-use the original Exception class and message
946 # but it is lost in the middle of the backtrace and encapsulated within 950 # but it is lost in the middle of the backtrace and encapsulated within
947 # a DBusException instance --> extract the data from the backtrace? 951 # a DBusException instance --> extract the data from the backtrace?
948 request.finish() 952 request.finish()
1046 self.signal_handler = SignalHandler(self) 1050 self.signal_handler = SignalHandler(self)
1047 _register = Register(self) 1051 _register = Register(self)
1048 _upload_radiocol = UploadManagerRadioCol(self) 1052 _upload_radiocol = UploadManagerRadioCol(self)
1049 _upload_avatar = UploadManagerAvatar(self) 1053 _upload_avatar = UploadManagerAvatar(self)
1050 self.signal_handler.plugRegister(_register) 1054 self.signal_handler.plugRegister(_register)
1051 self.sessions = {} #key = session value = user 1055 self.sessions = {} # key = session value = user
1052 self.prof_connected = set() #Profiles connected 1056 self.prof_connected = set() # Profiles connected
1053 self.action_handler = SATActionIDHandler() 1057 self.action_handler = SATActionIDHandler()
1054 ## bridge ## 1058 ## bridge ##
1055 try: 1059 try:
1056 self.bridge=DBusBridgeFrontend() 1060 self.bridge = DBusBridgeFrontend()
1057 except BridgeExceptionNoService: 1061 except BridgeExceptionNoService:
1058 print(u"Can't connect to SàT backend, are you sure it's launched ?") 1062 print(u"Can't connect to SàT backend, are you sure it's launched ?")
1059 sys.exit(1) 1063 sys.exit(1)
1064
1060 def backendReady(dummy): 1065 def backendReady(dummy):
1061 self.bridge.register("connected", self.signal_handler.connected) 1066 self.bridge.register("connected", self.signal_handler.connected)
1062 self.bridge.register("disconnected", self.signal_handler.disconnected) 1067 self.bridge.register("disconnected", self.signal_handler.disconnected)
1063 self.bridge.register("connectionError", self.signal_handler.connectionError) 1068 self.bridge.register("connectionError", self.signal_handler.connectionError)
1064 self.bridge.register("actionResult", self.action_handler.actionResultCb) 1069 self.bridge.register("actionResult", self.action_handler.actionResultCb)