SF.net SVN: fclient: [274] trunk/sandbox/fcp2/client.py
Status: Pre-Alpha
Brought to you by:
jurner
|
From: <ju...@us...> - 2008-02-26 15:53:56
|
Revision: 274
http://fclient.svn.sourceforge.net/fclient/?rev=274&view=rev
Author: jurner
Date: 2008-02-26 07:53:48 -0800 (Tue, 26 Feb 2008)
Log Message:
-----------
beautifications
Modified Paths:
--------------
trunk/sandbox/fcp2/client.py
Modified: trunk/sandbox/fcp2/client.py
===================================================================
--- trunk/sandbox/fcp2/client.py 2008-02-26 15:30:00 UTC (rev 273)
+++ trunk/sandbox/fcp2/client.py 2008-02-26 15:53:48 UTC (rev 274)
@@ -177,13 +177,13 @@
# TODO: check if this is a bug in Fcp
# NOTE: seems to be fixed in [build 1112], fixes removed
#-------------------------------------------------------------------------------------------------------------------------------------------------
+import os, sys
+
import atexit
import copy
import logging
-import os
import socket
import subprocess
-import sys
import time
@@ -196,13 +196,12 @@
def __del__(self): sys.path.pop(0)
hack = _RelImportHack(2)
-
from fcp2 import consts
-from fcp2.config import Config
-from fcp2.events import Events
-from fcp2.message import Message
-import fcp2.params as FcParams
-from fcp2.uri import Uri
+from fcp2 import config
+from fcp2 import events
+from fcp2 import message
+from fcp2 import fcparams
+from fcp2 import uri
from fcp2.fcp_lib import namespace
from fcp2.fcp_lib import tools
@@ -239,10 +238,10 @@
ExpectedNodeBuild = 1107
consts = consts
- Config = Config
- Message = Message
- FcParams = FcParams
- Uri = Uri
+ config = config
+ message = message
+ fcparams = fcparams
+ Uri = uri
def __init__(self,
@@ -256,23 +255,21 @@
"""
self._connectionName = self.setConnectionName(connectionName)
self._ddaTests = [] # currently running DDA tests (request0, ... requestN)
- self._requests = {} # currently running requests (requestIdentifier --> request)
-
- self._logEvent = logging.getLogger(consts.LoggerNames.ClientEvents)
- self._logMessage = logging.getLogger(consts.LoggerNames.ClientMessages)
- self._logRuntime = logging.getLogger(consts.LoggerNames.ClientRuntime)
-
+ self.events = events.Events()
+ self._loggers = {
+ 'Event': logging.getLogger(consts.LoggerNames.ClientEvents),
+ 'Message': logging.getLogger(consts.LoggerNames.ClientMessages),
+ 'Runtime': logging.getLogger(consts.LoggerNames.ClientRuntime),
+ }
self._nodeHelloMessage = None
+ self._requests = {} # currently running requests (requestIdentifier --> request)
self._socket = None
-
- self.events = Events()
+
for event in self.events:
event += self._captureEvent
-
self.setDebugVerbosity(consts.DebugVerbosity.Warning if debugVerbosity is None else debugVerbosity)
atexit.register(self.close)
-
-
+
###############################################################
##
## private methods
@@ -282,7 +279,7 @@
"""Closes the client
@param msg: message to pass to the ClientDisconnected event or None to not inform listeners
"""
- self._logRuntime.info(consts.LogMessages.ClientClose)
+ self._loggers['Runtime'].info(consts.LogMessages.ClientClose)
# clean left over DDA test tmp files
for initialRequest in self._ddaTests:
@@ -352,7 +349,7 @@
@return: (str) identifer of therequest
@note: the identifier returned is unique to the client but may not be unique to the node
"""
- identifier = self.FcParams.newUuid(uuids=self._requests) if identifier is None else identifier
+ identifier = fcparams.newUuid(uuids=self._requests) if identifier is None else identifier
if requestType & (consts.RequestType.MaskGet | consts.RequestType.MaskPut):
@@ -393,7 +390,7 @@
})
# equip msg with some persistent pparams
if msg.get('ClientToken', None) is None:
- msg['ClientToken'] = self.FcParams.messageToParams(msg)
+ msg['ClientToken'] = fcparams.messageToParams(msg)
elif requestType & consts.RequestType.MaskGenerateKeypair:
msg.params.update({
@@ -433,7 +430,7 @@
def _captureEvent(self, event, request):
if event != self.events.Idle:
- self._logEvent.debug(consts.LogMessages.EventTriggered + event.name)
+ self._loggers['Event'].debug(consts.LogMessages.EventTriggered + event.name)
###############################################################
##
@@ -444,7 +441,7 @@
"""Closes the client
@note: make shure to call close() when done with the client
"""
- msg = self.Message(
+ msg = message.Message(
consts.Message.ClientDisconnected,
DisconnectReason=consts.DisconnectReason.Close,
Param=None,
@@ -483,7 +480,7 @@
@event: ClientConnected(event, message) is triggered as soon as the client is connected
"""
- self._logRuntime.info(consts.LogMessages.Connecting)
+ self._loggers['Runtime'].info(consts.LogMessages.Connecting)
# try to Connect socket
if self._socket is not None:
@@ -503,7 +500,7 @@
except socket.error, d:
yield None
else:
- self._logRuntime.info(consts.LogMessages.Connected)
+ self._loggers['Runtime'].info(consts.LogMessages.Connected)
# send ClientHello and wait for NodeHello
#NOTE: thought I could leave ClientHelloing up to the caller
@@ -528,7 +525,7 @@
if self.versionCheckNodeHello(msg):
self.events.ClientConnected(msg)
else:
- disconnectMsg = self.Message(
+ disconnectMsg = message.Message(
consts.Message.ClientDisconnected,
DisconnectReason=consts.DisconnectReason.VersionMissmatch,
Param=msg,
@@ -538,17 +535,17 @@
raise StopIteration
else:
- self._logMessage.debug(consts.LogMessages.MessageReceived + msg.pprint())
+ self._loggers['Message'].debug(consts.LogMessages.MessageReceived + msg.pprint())
break
break
# continue polling
- self._logRuntime.info(consts.LogMessages.ConnectionRetry)
+ self._loggers['Runtime'].info(consts.LogMessages.ConnectionRetry)
timeElapsed += timeout
time.sleep(timeout)
- self._logRuntime.info(consts.LogMessages.ConnectingFailed)
- disconnectMsg = self.Message(
+ self._loggers['Runtime'].info(consts.LogMessages.ConnectingFailed)
+ disconnectMsg = message.Message(
consts.Message.ClientDisconnected,
DisconnectReason=consts.DisconnectReason.ConnectingFailed,
Param=None,
@@ -569,7 +566,7 @@
@param connectionName: (str) connection name or None to use an arbitrary connection name
@return: (str) connection name
"""
- self._connectionName = self.FcParams.newUuid() if connectionName is None else connectionName
+ self._connectionName = fcparams.newUuid() if connectionName is None else connectionName
return self._connectionName
@@ -577,11 +574,10 @@
"""Sets the verbosity level of the client
@note: see L{consts.DebugVerbosity}
"""
- self._logEvent.setLevel(debugVerbosity)
- self._logMessage.setLevel(debugVerbosity)
- self._logRuntime.setLevel(debugVerbosity)
-
+ for logger in self._loggers.values():
+ logger.setLevel(debugVerbosity)
+
def startFreenet(self, cmdline):
"""Starts freenet
@param cmdline: commandline to start freenet (like '/freenet/run.sh start' or 'c:\freenet\start.bat')
@@ -635,7 +631,7 @@
return False
# resend request with new identifier
- newIdentifier = self.FcParams.newUuid(uuids=self._requests)
+ newIdentifier = fcparams.newUuid(uuids=self._requests)
self._requests[newIdentifier] = initialRequest
del self._requests[requestIdentifier]
initialRequest['Identifier'] = newIdentifier
@@ -648,7 +644,7 @@
elif msg.name == consts.Message.ProtocolError:
code = msg['Code']
if code == consts.ProtocolError.ShuttingDown:
- disconnectMsg = self.Message(
+ disconnectMsg = message.Message(
consts.Message.ClientDisconnected,
DisconnectReason=consts.DisconnectReason.Shutdown,
Param=None,
@@ -667,7 +663,7 @@
# handle DDA errors
elif code == consts.ProtocolError.DDADenied:
- ddaRequestMsg = self.Message(consts.Message.TestDDARequest)
+ ddaRequestMsg = message.Message(consts.Message.TestDDARequest)
if initialRequest.name == consts.Message.ClientGet:
ddaRequestMsg['WantWriteDirectory'] = True
directory = os.path.dirname(initialRequest['Filename'])
@@ -897,7 +893,7 @@
# unknown request... try to restore it
if initialRequest is None:
- fcParams = self.FcParams.paramsFromRequest(msg)
+ fcParams = fcparams.paramsFromRequest(msg)
# not one of our requests... so cancel it
if fcParams is None or CancelPersistentRequests:
@@ -911,12 +907,12 @@
initialRequest = copy.deepcopy(msg)
self._registerRequest(
initialRequest,
- fcParams[self.FcParams.IRequestType],
+ fcParams[fcparams.IRequestType],
identifier=requestIdentifier,
- initTime=fcParams[self.FcParams.IInitTime],
+ initTime=fcParams[fcparams.IInitTime],
userData=None,
- persistentUserData=fcParams[self.FcParams.IPersistentUserData],
- filenameCollision=fcParams[self.FcParams.IFilenameCollision],
+ persistentUserData=fcParams[fcparams.IPersistentUserData],
+ filenameCollision=fcParams[fcparams.IFilenameCollision],
)
initialRequest.name = consts.Message.ClientGet
@@ -940,7 +936,7 @@
modified = {}
# check if PersistentUserData has changed
- params = self.FcParams.paramsFromRequest(initialRequest)
+ params = fcparams.paramsFromRequest(initialRequest)
if params is not None:
clientToken = msg.get('ClientToken', None)
if clientToken is not None:
@@ -950,7 +946,7 @@
# otherwise we would have to set flags to indicate wich member
# of ClientToken changed. See --> modifyRequest()
modified[consts.RequestModified.PersistentUserData] = None
- for i, fcParam in enumerate(self.FcParams.FcParams):
+ for i, fcParam in enumerate(fcparams.FcParams):
initialRequest[fcParam] = params[i]
# check if PriorityClass has changed
@@ -991,7 +987,7 @@
# unknown request... try to restore it
if initialRequest is None:
- fcParams = self.FcParams.paramsFromRequest(msg)
+ fcParams = fcparams.paramsFromRequest(msg)
# not one of our requests... so cancel it
if fcParams is None or CancelPersistentRequests:
@@ -1003,15 +999,15 @@
return True
initialRequest = copy.deepcopy(msg)
- requestType = fcParams[self.FcParams.IRequestType]
+ requestType = fcParams[fcparams.IRequestType]
self._registerRequest(
initialRequest,
requestType,
identifier=requestIdentifier,
- initTime=fcParams[self.FcParams.IInitTime],
+ initTime=fcParams[fcparams.IInitTime],
userData=None,
- persistentUserData=fcParams[self.FcParams.IPersistentUserData],
- filenameCollision=fcParams[self.FcParams.IFilenameCollision],
+ persistentUserData=fcParams[fcparams.IPersistentUserData],
+ filenameCollision=fcParams[fcparams.IFilenameCollision],
)
# determine initial message name
@@ -1146,7 +1142,7 @@
##
####################################################
elif msg.name == consts.Message.CloseConnectionDuplicateClientName:
- disconnectMsg = self.Message(
+ disconnectMsg = message.Message(
consts.Message.ClientDisconnected,
DisconnectReason=consts.DisconnectReason.DuplicateClientName,
Param=None,
@@ -1160,8 +1156,8 @@
return False
#TODO:no idea if the node may pass uris with prefixes like 'freenet:'... strip it anyways
- insertURI = self.Uri(msg['InsertURI']).uri
- requestURI = self.Uri(msg['RequestURI']).uri
+ insertURI = uri.Uri(msg['InsertURI']).uri
+ requestURI = uri.Uri(msg['RequestURI']).uri
if initialRequest['FcRequestType'] == consts.RequestType.GenerateUSKKeypair:
insertURI = insertURI.replace(consts.KeyType.SSK, consts.KeyType.USK, 1)
@@ -1190,11 +1186,11 @@
@note: use this method to run the client step by step. If you want to run the
client unconditionally use L{run}
"""
- msg = self.Message.fromSocket(self._socket)
+ msg = message.Message.fromSocket(self._socket)
if msg.name == consts.Message.ClientSocketDied:
- self._logRuntime.critical(consts.LogMessages.SocketDied)
+ self._loggers['Runtime'].critical(consts.LogMessages.SocketDied)
if dispatch:
- disconnectMsg = self.Message(
+ disconnectMsg = message.Message(
consts.Message.ClientDisconnected,
DisconnectReason=consts.DisconnectReason.SocketDied,
Param=msg,
@@ -1206,7 +1202,7 @@
if dispatch:
self.events.Idle(msg)
else:
- self._logMessage.debug(consts.LogMessages.MessageReceived + msg.pprint())
+ self._loggers['Message'].debug(consts.LogMessages.MessageReceived + msg.pprint())
if dispatch:
self.handleMessage(msg)
return msg
@@ -1224,7 +1220,7 @@
try:
msg = self.next()
except KeyboardInterrupt:
- self._logRuntime.info(consts.LogMessages.KeyboardInterrupt)
+ self._loggers['Runtime'].info(consts.LogMessages.KeyboardInterrupt)
return
if msg.name == consts.Message.ClientSocketDied:
return
@@ -1242,13 +1238,13 @@
break
if not haveRunningRequests:
- self._logRuntime.info(consts.LogMessages.AllRequestsCompleted)
+ self._loggers['Runtime'].info(consts.LogMessages.AllRequestsCompleted)
break
try:
msg = self.next()
except KeyboardInterrupt:
- self._logRuntime.info(consts.LogMessages.KeyboardInterrupt)
+ self._loggers['Runtime'].info(consts.LogMessages.KeyboardInterrupt)
break
if msg.name == consts.Message.ClientSocketDied:
@@ -1268,7 +1264,7 @@
@note: you can use this method to send a message to the node, bypassing all
track keeping methods of the client
"""
- return self.sendMessageEx(self.Message(name, data=data, **params))
+ return self.sendMessageEx(message.Message(name, data=data, **params))
def sendMessageEx(self, msg):
@@ -1282,15 +1278,15 @@
@note: you can use this method to send a message to the node, bypassing all
track keeping methods of the client
"""
- self._logMessage.debug(consts.LogMessages.MessageSend + msg.pprint())
+ self._loggers['Message'].debug(consts.LogMessages.MessageSend + msg.pprint())
try:
msg.send(self._socket)
except socket.error, d:
- self._logRuntime.critical(consts.LogMessages.SocketDied)
- disconnectMsg = self.Message(
+ self._loggers['Runtime'].critical(consts.LogMessages.SocketDied)
+ disconnectMsg = message.Message(
consts.Message.ClientDisconnected,
DisconnectReason=consts.DisconnectReason.SocketDied,
- Param=self.Message(consts.Message.ClientSocketDied, Exception=socket.error, Details=d)
+ Param=message.Message(consts.Message.ClientSocketDied, Exception=socket.error, Details=d)
)
self._close(disconnectMsg)
raise socket.error(d)
@@ -1331,7 +1327,7 @@
"""Modifies node configuration values
@param params: (dict) containing parameters to modify
"""
- msg = self.Message(consts.Message.ModifyConfig)
+ msg = message.Message(consts.Message.ModifyConfig)
msg.params = params
self.sendMessageEx(msg)
@@ -1342,7 +1338,7 @@
##
########################################################
def clientGet(self,
- uri,
+ key,
requestType,
userData,
persistentUserData,
@@ -1350,7 +1346,7 @@
**messageParams
):
"""Requests a key from the node
- @param uri: (str) uri of the file to request (may contain prefixes like 'freenet:' or 'http://')
+ @param key: (str) key or Uri of the file to request (may contain prefixes like 'freenet:' or 'http://')
@param requestType: (L{consts.RequestType}) sub type of the message
@param userData: any non persistent data to associate to the request or None
@param persistentUserData: any string to associate to the request as persistent data or None
@@ -1360,8 +1356,8 @@
@return: (str) identifier of the request
"""
- uri = self.Uri(uri).uri
- msg = self.Message(consts.Message.ClientGet, URI=uri)
+ key = uri.Uri(key).uri
+ msg = message.Message(consts.Message.ClientGet, URI=key)
for paramName, value in messageParams.items():
if value is not None:
msg[paramName] = value
@@ -1379,7 +1375,7 @@
def getData(self,
- uri,
+ key,
allowedMimeTypes=None,
binaryBlob=False,
@@ -1395,7 +1391,7 @@
):
"""Requests datae from the node
- @param uri: uri of the data to request (may contain prefixes like 'freenet:' or 'http://')
+ @param key: (str) key or Uri of the data to request (may contain prefixes like 'freenet:' or 'http://')
@param allowedMimeTypes: (str) list of allowed mime types
@param binaryBlob: (bool) if True, the file is retrieved as binary blob file
@@ -1410,10 +1406,10 @@
@return: (str) request identifier
- @event: L{Events.RequestCompleted} triggered as soon as the request is complete
- @event: L{Events.RequestFailed} triggered if the request failes
- @event: L{Events.RequestStarted} triggered as soon as the request is started
- @event: L{Events.RequestModified} trigggered if the request identifier changes
+ @event: L{events.RequestCompleted} triggered as soon as the request is complete
+ @event: L{events.RequestFailed} triggered if the request failes
+ @event: L{events.RequestStarted} triggered as soon as the request is started
+ @event: L{events.RequestModified} trigggered if the request identifier changes
or the request is modified otherwise (see L{modifyRequest})
@note: the identifier of the request may change at any time. You should be prepaired to handle
@@ -1422,7 +1418,7 @@
as soon as it completes or failes
"""
return self.clientGet(
- uri,
+ key,
consts.RequestType.GetData,
userData,
persistentUserData,
@@ -1440,13 +1436,12 @@
Persistence=persistence,
PriorityClass=priorityClass,
ReturnType=consts.ReturnType.Direct,
- URI=self.Uri(uri).uri,
Verbosity=consts.Verbosity.ReportProgress,
)
def getFile(self,
- uri,
+ key,
filename,
allowedMimeTypes=None,
@@ -1464,7 +1459,7 @@
):
"""Requests a file from the node
- @param uri: uri of the file to request (may contain prefixes like 'freenet:' or 'http://')
+ @param key: (str) key or Uri of the file to request (may contain prefixes like 'freenet:' or 'http://')
@param filename: (full path) filename to store the file to
@param allowedMimeTypes: (str) list of allowed mime types
@@ -1491,7 +1486,7 @@
as soon as it completes or failes
"""
return self.clientGet(
- uri,
+ key,
consts.RequestType.GetFile,
userData,
persistentUserData,
@@ -1510,13 +1505,12 @@
Persistence=persistence,
PriorityClass=priorityClass,
ReturnType=consts.ReturnType.Disk,
- URI=self.Uri(uri).uri,
Verbosity=consts.Verbosity.ReportProgress,
)
def getKeyInfo(self,
- uri,
+ key,
dsOnly=False,
ignoreDS=False,
@@ -1529,7 +1523,7 @@
):
"""Requests info about a key
- @param uri: uri of the file to request (may contain prefixes like 'freenet:' or 'http://')
+ @param key: (str) key or Uri of the file to request (may contain prefixes like 'freenet:' or 'http://')
@param dsOnly: if True, retrieves the file from the local data store only
@param ignoreDS: If True, ignores the local data store
@@ -1552,7 +1546,7 @@
"""
# how to retrieve meta info about a key? ...idea is to provoke a GetFailed (TooBig)
return self.clientGet(
- uri,
+ key,
consts.RequestType.GetKeyInfo,
userData,
persistentUserData,
@@ -1568,25 +1562,24 @@
Persistence=persistence,
PriorityClass=priorityClass,
ReturnType=consts.ReturnType.Nothing,
- URI=self.Uri(uri).uri,
Verbosity=consts.Verbosity.ReportProgress,
)
#TODO: persists until connection is closed... can this request be removed?
- def subscribeUSK(self, uri, dontPoll=True):
+ def subscribeUSK(self, key, dontPoll=True):
"""Asks the node to notify the client when an USK is updated
- @param uri: uri of the USK to subscribe to
+ @param key: (str) key or Uri of the USK to subscribe to
@param dontPoll: if True, does whatever ???
@return: (str) identifer of the request
@note: this request can not be removed or modified and the {consts.RequestStatus.Completed}
flag is always set
"""
- msg = self.Message(
+ msg = message.Message(
consts.Message.SubscribeUSK,
- URI=uri,
+ URI=uri.Uri(key).uri,
DontPoll=dontPoll,
)
self._registerRequest(msg, consts.RequestType.SubscribeUSK)
@@ -1602,7 +1595,7 @@
########################################################
def clientPut(self,
requestType,
- uri,
+ key,
data=None,
persistentUserData='',
userData=None,
@@ -1611,7 +1604,7 @@
):
"""Uploads to the node
@param requestType: (L{consts.RequestType}). Can be PutData, PutDir or PutMultiple
- @param uri:
+ @param key: (str) key or Uri
@param data: (str) for L{consts.RequestType.PutData} data to upload or None
@param persistentUserData: (str) persistent data to be assosiated to the request
@param userData: (any) any data to be associated to the request at runtime
@@ -1642,7 +1635,7 @@
else:
raise ValueError('Unsupported request type')
- msg = self.Message(msgName, URI=uri)
+ msg = message.Message(msgName, URI=key)
contentType = msgParams.get('ContentType', None)
if contentType is not None:
del msgParams['ContentType']
@@ -1724,7 +1717,7 @@
@param userData: (any) any data to be associated to the request at runtime
@return: (str) request identifier
"""
- msg = self.Message(
+ msg = message.Message(
consts.Message.ClientPut,
URI=consts.KeyType.KSK + name,
Persistence=persistence,
@@ -2045,21 +2038,21 @@
if persistentUserData is not None:
initialRequest['FcPersistentUserData'] = persistentUserData
- initialRequest['ClientToken'] = self.FcParams.messageToParams(initialRequest)
+ initialRequest['ClientToken'] = fcparams.messageToParams(initialRequest)
modified[consts.RequestModified.PersistentUserData] = None
initialRequest['FcModified'] = modified
self.events.RequestModified(initialRequest)
return
- msg = self.Message(
+ msg = message.Message(
consts.Message.ModifyPersistentRequest,
Identifier=initialRequest['Identifier'],
Global=False,
)
if persistentUserData is not None:
initialRequest['FcPersistentUserData'] = persistentUserData
- msg['ClientToken'] = self.FcParams.messageToParams(initialRequest)
+ msg['ClientToken'] = fcparams.messageToParams(initialRequest)
if priorityClass is not None:
msg['PriorityClass'] = priorityClass
@@ -2077,7 +2070,7 @@
# remove Persistence.Connection emidiately
# ..make up a PersistentRequestRemoved message for this case
if initialRequest['Persistence'] == consts.Persistence.Connection:
- msg = self.Message(consts.Message.PersistentRequestRemoved, Identifier=requestIdentifier, Global=False)
+ msg = message.Message(consts.Message.PersistentRequestRemoved, Identifier=requestIdentifier, Global=False)
self._finalizeRequest(msg, initialRequest, self.events.RequestRemoved)
else:
self.sendMessage(
@@ -2248,7 +2241,7 @@
@param detailed: (bool) If True, detailed information is returned
@return: (str) request identifier
"""
- msg = self.Message(
+ msg = message.Message(
consts.Message.GetPluginInfo,
PluginName=pluginName,
Detailed=detailed,
@@ -2265,7 +2258,7 @@
@param data: (str) data to pass along with the messaage or None
@return: (str) request identifier
"""
- msg = self.Message(
+ msg = message.Message(
consts.Message.FCPPluginMessage,
PluginName=pluginName,
**params
@@ -2288,7 +2281,7 @@
@param keypairType: type of keypair to generate (either L{consts.KeyType.SSK} or L{consts.KeyType.SSK})
@return: identifier of the request
- @event: L{Events.KeypairGenerated} triggered as soon as the request is complete
+ @event: L{events.KeypairGenerated} triggered as soon as the request is complete
@requestparam: B{FcModified:} (dict)
@requestparam: B{FcPrivateKey:} None. Will contain the private key as soon as the key is generated
@@ -2301,7 +2294,7 @@
raise ValueError('keypairType must be %s or %s' % (consts.KeyType.SSK, consts.KeyType.USK))
requestType = consts.RequestType.GenerateSSKKeypair if keypairType == consts.KeyType.SSK else consts.RequestType.GenerateUSKKeypair
- msg = self.Message(consts.Message.GenerateSSK)
+ msg = message.Message(consts.Message.GenerateSSK)
self._registerRequest(msg, requestType)
self.sendMessageEx(msg)
return msg['Identifier']
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|