summaryrefslogtreecommitdiffstats
path: root/python/pykde/extensions/dcopext.py
diff options
context:
space:
mode:
Diffstat (limited to 'python/pykde/extensions/dcopext.py')
-rw-r--r--python/pykde/extensions/dcopext.py721
1 files changed, 0 insertions, 721 deletions
diff --git a/python/pykde/extensions/dcopext.py b/python/pykde/extensions/dcopext.py
deleted file mode 100644
index 539c4d6c..00000000
--- a/python/pykde/extensions/dcopext.py
+++ /dev/null
@@ -1,721 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: ISO-8859-1 -*-
-
-"""
-Copyright 2004 Jim Bublitz (original author)
- 2006 Mathias Panzenböck (panzi) <grosser.meister.morti@gmx.net>
-
-Terms and Conditions
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to
-deal in the Software without restriction, including without limitation the
-rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-sell copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
-IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-
-Except as contained in this notice, the name of the copyright holder shall
-not be used in advertising or otherwise to promote the sale, use or other
-dealings in this Software without prior written authorization from the
-copyright holder.
-"""
-
-import re
-from dcop import DCOPClient
-from qt import QString, QCString, QByteArray, QDataStream, IO_ReadOnly, IO_WriteOnly
-from kdecore import dcop_add, dcop_next
-
-# XXX: 64 bit integers might be handeld wrong! pythons int is AFAIK 32 bit,
-# but pythons long is a arbitrary-precision integer. how to handle that?
-#
-# I think 64 bit types would be:
-# long long, unsigned long long, long long int, unsigned long long int,
-# Q_LLONG, Q_ULLONG, Q_INT64, Q_UINT64
-#
-# and on some (most?) systems:
-# QtOffset
-
-# add complex? complex is c99, not c++
-# but python has a complex type
-POD = set(['char','short','int','long','float','double'])
-typedefIntTypes = set(["uchar", "ushort", "uint", "ulong",
- "Q_INT8", "Q_INT16", "Q_INT32", "Q_LONG",
- "Q_UINT8", "Q_UINT16", "Q_UINT32", "Q_ULONG",
- "sitze_t", "ssize_t", "int8_t", "int16_t", "int32_t",
- "uint8_t", "uint16_t", "uint32_t", "pid_t", "uid_t",
- "off_t"])
-# XXX string and std::string too?
-stringTypes = set(["QString", "QCString"])
-pythonStringTypes = set([QString, QCString, str])
-stringTypesDict = {"QString":QString,"QCString":QCString,"str":str,"unicode":unicode}
-
-VOID = 0
-BOOLEAN = 1 # XXX bool is not supported by dcop_add, but maybe some time...
-INTEGER = 2
-FLOAT = 3
-STRING = 4
-CLASS = 5
-
-"""
-(Most of this code is adapted from pydcop in kde-bindings, written by
-Torben Weis and Julian Rockey)
-
-The three classes below (DCOPApp, DCOPObj and DCOPMeth)
-allow transparent Python calls to DCOP methods. For example:
-
- d = DCOPApp ("kicker", dcop)
-
-(where "kicker" is the complete name of an application and 'dcop' is
-the dcopClient instance owned by the KApplication creating the DCOPApp
-instance) creates a DCOPApp instance. All of the classes in this
-file "borrow" a DCOPClient instance from the calling application.
-
- d.objects
-
-will return a list of the DCOP objects the application supplies.
-
- o = d.object ("Panel")
-
-will return a DCOPObj corresponding to applications "Panel" DCOP object.
-
-Similarly:
-
- o.methods
-
-will return a list of the methods the object supplies and
-
- m = o.method ("panelSize")
-
-will return a DCOPMeth corresponding to Panel's panelSize() method.
-The m instance also holds the methods return type, list of argument types
-(argtypes) and argument names (argnames).
-
- m.valid
-
-is a boolean which indicates if the method encapsulated by m is a valid
-method for the application/object specified.
-
-However it isn't necessary to explicitly create the DCOPObj and DCOPMeth.
-
- d.Panel.panelSize.valid
-
-for example, will also indicate if the method is valid without creating the
-intermediate 'o' and 'm' instances explicitly.
-
- d = DCOPApp ("kicker", dcop)
- ok, res = d.Panel.panelSize ()
-
-is all the code necessary to perform the indicated DCOP call and return the
-value the call returns. In this case, panelSize takes no arguments and
-returns an int. 'ok' returns the status of the DCOP call (success = True,
-failure = False).
-
- ok = d.Panel.addURLButton (QString ("http://www.kde.org"))
-
-would call addURLButton with the required argument, and return nothing but the DCOP call
-status(since its return type is 'void').
-
-Note that to instantiate a DCOPObj directly, you need to have a valid DCOPApp
-to pass to DCOPObj's __init__ method. Similarly, DCOPMeth requires a valid DCOPOBject.
-For example:
-
- d = DCOPApp ("kicker", dcop)
- o = DCOPObj (d, "Panel")
- m = DCOPMeth (o, "panelSize")
-
-or
-
- m = DCOPMeth (DCOPObj (DCOPApp ("kicker", dcop), "Panel"), "panelSize")
-
-"""
-
-# support stuff:
-def _xiter(*seqences):
- iters = [iter(seq) for seq in seqences]
-
- try:
- while True:
- yield [it.next() for it in iters]
-
- except StopIteration:
- pass
-
-def isStringType(s):
- for stringType in pythonStringTypes:
- if isinstance(s,stringType):
- return True
- return False
-
-# method syntax:
-# --------------
-# method ::= rtype identifier( args )
-# rtype ::= "void" | type
-# identifier ::= [_a-zA-Z][_a-zA-Z0-9]*
-# args ::= ( arg ("," arg)* )?
-# arg ::= type identifier?
-# type ::= namespace typespec | POD
-# POD ::= ( "unsigned" | "signed" )? identifier
-# namespace ::= (identifier "::")* | "::"
-# typespec ::= identifier ( "<" tpyelist ">" )?
-# typelist ::= (type | int) ("," (type | int) )*
-# int ::= "0x" [0-9a-fA-F]+ | [0-9]+
-
-class MethodParser(object):
- ident_r = re.compile("[_a-zA-Z][_a-zA-Z0-9]*")
- num_r = re.compile("0x[0-0a-fA-F]+|[0-9]+")
-
- def __init__(self,method):
- self.method = str(method)
- self.rtype = None
- self.name = None
- self.args = []
-
- self.parseMethod()
-
- def __repr__(self):
- return "%s(%s)" % (self.__class__.__name__, repr(self.method))
-
- def getDecl(self):
- return ''.join([self.name, '(', ','.join(argtp for (argtp, kind), argname in self.args), ')'])
-
- def parseMethod(self):
- i = self.parseRtype(self.method,0)
- i, self.name = self.parseIdentifier(self.method,i)
- i = self.parseArgs(self.method,i)
-
- if i != len(self.method):
- raise SyntaxError, "invalid function definition: %s" % self.method
-
- @staticmethod
- def skipws(s,i):
- while s[i:i+1].isspace():
- i += 1
- return i
-
- def parseArg(self,s,i):
- i, tp = self.parseType(s,i)
- name = self.parseIdentifier(s,i)
-
- if name:
- i, name = name
- else:
- name = None
-
- return i, (tp, name)
-
- def parseIdentifier(self,s,i):
- i = MethodParser.skipws(s,i)
- m = MethodParser.ident_r.match(s,i)
-
- if m:
- return m.end(), s[i:m.end()]
- else:
- return False
-
- def parseInteger(self,s,i):
- i = MethodParser.skipws(s,i)
- m = MethodParser.num_r.match(s,i)
-
- if m:
- return m.end(), s[i:m.end()]
- else:
- return False
-
- def parseArgs(self,s,i):
- i = MethodParser.skipws(s,i)
-
- if s[i:i+1] == '(':
- i += 1
- i = MethodParser.skipws(s,i)
-
- while i < len(s) and s[i:i+1] != ')':
- i, arg = self.parseArg(s,i)
- i = MethodParser.skipws(s,i)
-
- self.args.append(arg)
-
- if s[i:i+1] == ',':
- i += 1
-
- else:
- break
-
- if s[i:i+1] == ')':
- i += 1
- else:
- raise SyntaxError, "missing ')'."
- else:
- raise SyntaxError, "missing '('."
-
- return i
-
- def parseType(self,s,i):
- num = self.parseNumberType(s,i)
-
- if num:
- return num
-
- i, ns = self.parseNamespace(s,i)
- i, tp = self.parseTypespec(s,i)
-
- tp = ns + tp
-
- if tp in stringTypes:
- return i, (tp, STRING)
-
- else:
- return i, (tp, CLASS)
-
- def parseTypespec(self,s,i):
- i, tp = self.parseIdentifier(s,i)
- i, tplst = self.parseTypelist(s,i)
-
- return i, tp + tplst
-
- def parseTypelist(self,s,i):
- L = []
- newi = MethodParser.skipws(s,i)
-
- if s[newi:newi+1] == '<':
- i = newi + 1
- i = MethodParser.skipws(s,i)
-
- L.append('<')
-
- while i < len(s) and s[i:i+1] != '>':
- # template-parameter can be integers!!
-
- num = self.parseInteger(s,i)
-
- if num:
- i, tp = num
-
- else:
- i, (tp, kind) = self.parseType(s,i)
-
- i = MethodParser.skipws(s,i)
-
- L.append(tp)
-
- if s[i:i+1] == ',':
- i += 1
- L.append(',')
-
- else:
- break
-
-
- if s[i:i+1] == '>':
- i += 1
- L.append('>')
-
- else:
- raise SyntaxError, "missing '>'."
-
- return i, ''.join(L)
-
- def parseNumberType(self,s,i):
- i, tp = self.parseIdentifier(s,i)
- L = []
-
- if tp == 'bool':
- return i, (tp, BOOLEAN)
-
- elif tp in typedefIntTypes:
- return i, (tp, INTEGER)
-
- elif tp in ('signed','unsigned'):
- L.append(tp)
- next = self.parseIdentifier(s,i)
-
- if next and next[1] in POD:
- i, tp = next
-
- else:
- # type can be fully quallyfied here!
- return i, (tp, INTEGER)
-
- if tp in POD:
- L.append(tp)
-
- else:
- # else no number-type at all!
-
- return False
-
- # long
- # long int
- # long long
- # long long int
- # long double
- # short
- # short int
-
- if tp == 'short':
- # short
-
- next = self.parseIdentifier(s,i)
-
- if next and next[1] == 'int':
- # short int
-
- i, tp = next
- L.append(tp)
-
- elif tp == 'long':
- # long
-
- next = self.parseIdentifier(s,i)
-
- if next:
- if next[1] in ('int', 'double'):
- # long int
- # long double
-
- i, tp = next
- L.append(tp)
-
- elif next[1] == 'long':
- # long long
- # XXX: this is 64bit! how should I handle this?
-
- i, tp = next
- L.append(tp)
-
- next = self.parseIdentifier(s,i)
-
- if next and next[1] == 'int':
- # long long int
-
- i, tp = next
- L.append(tp)
-
- if tp in ('float', 'double'):
- return i, (' '.join(L), FLOAT)
-
- else:
- return i, (' '.join(L), INTEGER)
-
- #
- # ::
- # foo::
- # ::foo::
- # foo::bar::
- # ::foo::bar::
- # ...
- def parseNamespace(self,s,i):
- L = []
- i = MethodParser.skipws(s,i)
-
- if s[i:i+2] == "::":
- i += 2
- L.append("::")
-
- while i < len(s):
- ns = self.parseIdentifier(s,i)
-
- if not ns:
- break
-
- newi, ns = ns
- newi = MethodParser.skipws(s,newi)
-
- if s[newi:newi+2] != "::":
- break
-
- i = newi + 2
-
- L.append( ns )
- L.append( "::" )
-
- return i, ''.join(L)
-
-
- def parseRtype(self,s,i):
- tp = self.parseIdentifier(s,i)
-
- if tp and tp[1] == 'void':
- i, tp = tp
- self.rtype = (tp,VOID)
-
- else:
- i, self.rtype = self.parseType(s,i)
-
- return i
-
-def DCOPAppsIter(client):
- for app in client.registeredApplications():
- yield str(app)
-
-class DCOPApp(object):
- """
- An object corresponding to an application with a DCOP interface
-
- Can return a list of the DCOP objects the application exposes,
- or create and return an instance of a specific DCOP object.
- """
- def __init__ (self, name, client):
- self.appname = name
- self.appclient = client
-
- def __getattr__ (self, item ):
- if item == "objects":
- objs, ok = self.appclient.remoteObjects(self.appname)
-
- if ok:
- return objs
- else:
- return None
-
- return DCOPObj(self, item)
-
- def __iter__(self):
- objs, ok = self.appclient.remoteObjects(self.appname)
-
- if ok:
- for obj in objs:
- yield str(obj)
-
- # sometimes a object-name is not a valid python identifier.
- # in that case you can use dcopapp['non-valid::object/name']
- def __getitem__(self,name):
- return DCOPObj(self, name)
-
- def object (self, object):
- return DCOPObj (self, object)
-
- def __repr__(self):
- return '%s(%s,%s)' % (self.__class__.__name__,repr(self.appname),repr(self.appclient))
-
- def __str__(self):
- return repr(self)
-
-class DCOPObj(object):
- """
- An object corresponding to a specific DCOP object owned by a
- specific application with a DCOP interface
-
- Can return a list of the DCOP methods the object exposes,
- or create and return an instance of a specific DCOP method.
- """
-
- def __init__ (self, *args):
- if isStringType(args[0]):
- self.appname = args [0]
- self.objclient = args [1]
- self.objname = args [2]
- else:
- self.appname = args [0].appname
- self.objname = args [1]
- self.objclient = args [0].appclient
-
- self.objmethods = self.getMethods()
-
- def __repr__( self ):
- return "%s(%s,%s)" % (self.__class__.__name__,repr(self.appname), repr(self.objname))
-
- def __str__( self ):
- return repr(self)
-
- def __getattr__( self, item ):
- if item == "methods":
- return self.objmethods
-
- return DCOPMeth(self, item)
-
- def __getitem__(self,name):
- return DCOPMeth(self, name)
-
- def getMethods(self):
- flist, ok = self.objclient.remoteFunctions(self.appname, self.objname)
-
- if ok:
- return flist
- else:
- return None
-
- def __iter__(self):
- flist, ok = self.objclient.remoteFunctions(self.appname, self.objname)
-
- if ok:
- for meth in flist:
- yield str(meth)
-
- def getMethodNames(self):
- return [MethodParser(meth).name for meth in self.objmethods]
-
- def getParsedMethods(self):
- return [MethodParser(meth) for meth in self.objmethods]
-
- def method(self, method):
- return DCOPMeth(self, method)
-
-class DCOPMeth(object):
- """
- An object corresponding to a specific DCOP method owned by a
- specific DCOP object.
- """
- def __init__(self, dcopObj, name):
- self.argtypes = []
- self.argnames = []
- self.fcnname = []
- self.rtype = []
- self.appname = dcopObj.appname
- self.objname = dcopObj.objname
- self.methname = name
- self.client = dcopObj.objclient
- self.methods = [str(meth) for meth in dcopObj.objmethods]
- self.valid = self.findMethod()
-#
-# if not self.valid:
-# self.fcnname = self.rtype = self.argtypes = self.argnames = None
-
- def __repr__( self ):
- return "%s(%s,%s,%s)" % (self.__class__.__name__,repr(self.appname),repr(self.objname),repr(self.methname))
-
- def __str__(self):
- return repr(self)
-
- def __call__(self, *args):
- return self.dcop_call(args)
-
- def __iter__(self):
- return iter(self.fcnname)
-
- def dcop_call(self, args):
- # method valid?
- if not self.valid:
- return False, None
-
- found = self.getMatchingMethod(args)
-
- if found is None:
- return False, None
-
- meth, argtypes = found
-
- ok, replyType, replyData = self.client.call(self.appname, self.objname, meth, self.__marshall(args,argtypes))
-
- if ok:
- return ok, self.__unmarshall(replyData, replyType)
- else:
- return ok, None
-
- def getMatchingMethod(self,args):
- count = len(args)
-
- for funct, argtypes in _xiter(self.fcnname, self.argtypes):
- if len(argtypes) == count:
- match = True
-
- for (wanttp, wantkind), have in _xiter(argtypes,args):
- if wantkind == BOOLEAN:
- if not isinstance(have, bool):
- match = False
- break
-
- elif wantkind == INTEGER:
- if not isinstance(have, int):
- match = False
- break
-
- elif wantkind == FLOAT:
- if not isinstance(have, float):
- match = False
- break
-
- elif wantkind == STRING:
- if not isStringType(have):
- match = False
- break
-
- elif wanttp != have.__class__.__name__:
- match = False
- break
-
- if match:
- return funct, argtypes
- return None
-
- def findMethod(self):
- has = False
-
- for meth in self.methods:
- fun = MethodParser(meth)
-
- if fun.name == self.methname:
- self.argtypes.append([argtp for argtp, argname in fun.args])
- self.argnames.append([argname for argtp, argname in fun.args])
- self.rtype.append(fun.rtype)
- self.fcnname.append(fun.getDecl())
-
- has = True
-
- return has
-
- def __marshall(self, args, argtypes):
- data = QByteArray()
- if argtypes == []:
- return data
-
- params = QDataStream (data, IO_WriteOnly)
-
- for arg, (argtype, argkind) in _xiter(args, argtypes):
- if argkind == BOOLEAN:
- # XXX for now, let bools be handelt like int
- dcop_add(params, int(arg), 'int')
-
- elif argkind in (INTEGER, FLOAT):
- dcop_add(params, arg, argtype)
-
- elif argkind == STRING:
- # convert it to the right string type:
- if argtype != arg.__class__.__name__:
- arg = stringTypesDict[argtype](arg)
-
- dcop_add(params, arg)
-
- elif argtype.startswith("QMap") or argtype.startswith("QValueList"):
- dcop_add(params, arg, argtype)
-
- # XXX:
- # Is 'isinstance(arg, eval(argtype))' really good?
- # What if 'argtype' is located in some modul? Like 'qt.QString'.
- # Then this will fail (but it should not!).
- # And the worst thing: the eval() will raise a NameError!
- #
- # On the other hand 'arg.__class__.__name__ == argtype' has the
- # disadvantage that it can't be a derived class!
- #
- # Would no check at all be better??
- #
- # But I doubt a derived class would be ok anyway. I have to check
- # this in the DCOP-docu, but I think a derived class would not be
- # correctly unmarshalled, because a derived class could be marshalled
- # in a total different way to it's super-class.
- elif arg.__class__.__name__ == argtype:
- dcop_add(params, arg)
-
- else:
- raise TypeError, "expected type %s, got type %s." % (argtype, arg.__class__.__name__)
-
- return data
-
- def __unmarshall(self, data, type_):
- s = QDataStream(data, IO_ReadOnly)
-
- if str(type_) in stringTypes:
- return str(dcop_next(s, type_))
- else:
- return dcop_next(s, type_)