OpenOffice.org Forum at OOoForum.orgThe OpenOffice.org Forum
 
 [Home]   [FAQ]   [Search]   [Memberlist]   [Usergroups]   [Register
 [Profile]   [Log in to check your private messages]   [Log in

obscure Jython/Python "reflection" question
Goto page 1, 2  Next
 
Post new topic   Reply to topic    OOoForum.org Forum Index -> OpenOffice.org Macros and API
View previous topic :: View next topic  
Author Message
mrodent33
Power User
Power User


Joined: 06 Nov 2010
Posts: 74

PostPosted: Thu Aug 11, 2011 1:19 pm    Post subject: obscure Jython/Python "reflection" question Reply with quote

hi,

actually it's not that obscure, except in the sense that not many people seem to be using Jython for OOo automation.

As we see here http://wiki.services.openoffice.org/wiki/PyUNO_samples
Code:
xModel = XSCRIPTCONTEXT.getDocument()
# the writer controller impl supports the css.view.XSelectionSupplier interface
xSelectionSupplier = xModel.getCurrentController()
xIndexAccess = xSelectionSupplier.getSelection()

... getting the Python code to convert an object with the Java class XController to the Java class XSelectionSupplier is a trivial operation.

But in Jython when I do
Code:
remoteServiceManager = remoteContext.getServiceManager()
# get access to toolkit of remote office to create the container window of new target frame
import com.sun.star as star
# sMGR = OOoUtils.getUnoInterface( star.lang.XMultiServiceFactory, remoteServiceManager);
sMGR = remoteServiceManager
toolkit = OOoUtils.getUnoInterface( star.awt.XToolkit, sMGR.createInstance("com.sun.star.awt.Toolkit"))

... it complains, Java-like: "AttributeError: '$Proxy12' object has no attribute 'createInstance'"
whereas if I uncomment the line which goes to fetch the XMultiServiceFactory (and comment out the next line) everything works fine.

Does anyone know whether this non-automatic reflection in Jython something which can be overcome? If not, does anyone know why Jython has this "lesser" reflection handling???

PS I have not been able to get Jython running from an OOo event, so this is all using the BootstrapSocketConnector
Back to top
View user's profile Send private message
hanya
Super User
Super User


Joined: 04 May 2005
Posts: 543
Location: Japan

PostPosted: Thu Aug 11, 2011 6:25 pm    Post subject: Reply with quote

Jython uses Java's objects to access OpenOffice.org API and it depends java style programing. Read Java's examples.
Quote:
Does anyone know whether this non-automatic reflection in Jython something which can be overcome? If not, does anyone know why Jython has this "lesser" reflection handling???
Make a wrapper object for the components from Java using css.script.Invocation service.
Back to top
View user's profile Send private message
hanya
Super User
Super User


Joined: 04 May 2005
Posts: 543
Location: Japan

PostPosted: Fri Aug 12, 2011 11:54 pm    Post subject: Reply with quote

I have written the wrapper for objects to write in Jython few years ago.

uno.py
Code:
from com.sun.star.uno import UnoRuntime, AnyConverter

def query(type, object):
    """ Query type interface from UNO object. """
    return UnoRuntime.queryInterface(type, object)

def getType(object):
    """ Get type of the UNO object. """
    return AnyConverter.getType(object)


UnoWrapper.py
Update 20110819.
Code:

from com.sun.star.uno import (Any as UnoAny,
    Type as UnoType, UnoRuntime, AnyConverter, XComponentContext)
from com.sun.star.uno.TypeClass import (ANY as TC_ANY,
     INTERFACE as TC_INTERFACE, SEQUENCE as TC_SEQUENCE,
     BOOLEAN as TC_BOOLEAN, BYTE as TC_BYTE,
     CHAR as TC_CHAR, SHORT as TC_SHORT,
     LONG as TC_LONG, HYPER as TC_HYPER,
     FLOAT as TC_FLOAT, DOUBLE as TC_DOUBLE,
     STRING as TC_STRING, TYPE as TC_TYPE,
     ENUM as TC_ENUM, STRUCT as TC_STRUCT)
from com.sun.star.script.MemberType import (
    METHOD as MT_METHOD, PROPERTY as MT_PROPERTY)
from com.sun.star.beans.MethodConcept import ALL as MC_ALL
from com.sun.star.beans.PropertyAttribute import READONLY as PA_READONLY
from com.sun.star.lang import XSingleServiceFactory
from com.sun.star.script import XInvocation2
from com.sun.star.beans import PropertyVetoException
from com.sun.star.lang import IllegalArgumentException
from com.sun.star.script import CannotConvertException


def query(type, object):
    """ Query type interface from UNO object. """
    return UnoRuntime.queryInterface(type, object)

def get_type(object):
    """ Get type of the UNO object. """
    return AnyConverter.getType(object)


class ExtType(UnoType):
    def __init__(self, _type):
        if isinstance(_type, UnoType):
            type_name = _type.getTypeName()
        else:
            type_name = _type 
        self.type = UnoType(type_name)
        self.comp_type = None
        if type_name.startswith("[]"):
            self.comp_type = ExtType(type_name[2:])
    def getTypeClass(self):
        return self.type.getTypeClass()
    def getTypeName(self):
        return self.type.getTypeName()
    def getComponentType(self):
        return self.comp_type



class Runtime(object):
   
    def __init__(self, ctx):
        ctx = query(XComponentContext, ctx)
        self.ctx = ctx
        self._invf = query(XSingleServiceFactory,
                ctx.getServiceManager().createInstanceWithContext(
                "com.sun.star.script.Invocation", ctx))
   
    def create_invocation(self, obj):
        return query(XInvocation2,
                     self._invf.createInstanceWithArguments([obj]))
   
    def wrap_for_info(self, info, value):
        return self.wrap_for_idl(ExtType(info.aType), value)
   
    def unwrap_for_info(self, info, value):
        return self.unwrap_for_idl(ExtType(info.aType), value)
   
    def unwrap_prepare_sequence(self, idl_class, args):
        carg = []
        try:
            for v in args:
                if isinstance(v, list) or isinstance(v, tuple):
                    carg.append(self.unwrap_prepare_sequence(idl_class, v))
                else:
                    carg.append(self.unwrap_for_idl(idl_class, v))
            return carg
        except:
            return args
   
    def unwrap_sequence(self, idl_class, seq):
        component_idl_class = self.get_component_type(idl_class)
        component_type_class = component_idl_class.getTypeClass()
        if component_type_class == TC_INTERFACE or \
            component_type_class == TC_STRUCT or component_type_class == TC_ANY:
            return self.unwrap_prepare_sequence(component_idl_class, seq)
        else:
            return seq
   
    def get_type_for_array(self, idl_class):
        dimension = idl_class.getName().count("[]")
        component_idl_class = self.get_component_type(idl_class)
        #type_name = component_idl_class.getName()
        component_type_class = component_idl_class.getTypeClass()
        if component_type_class == TC_INTERFACE:
            sig = component_idl_class.getName()
        elif component_type_class == TC_STRUCT:
            sig = component_idl_class.getName()
        elif component_type_class == TC_ANY:
            #sig = component_idl_class.getName()
            sig = "Ljava.lang.Object;"
        elif component_type_class == TC_BOOLEAN:
            sig = "Z"
        elif component_type_class == TC_STRING:
            sig = "Ljava.lang.String;"
        elif component_type_class == TC_BYTE:
            sig = "B"
        elif component_type_class == TC_CHAR:
            sig = "C"
        elif component_type_class == TC_SHORT:
            sig = "S"
        #elif component_type_class == TC_INTEGER:
        #    sig = "I"
        # range of integer type value should be checked
        elif component_type_class == TC_LONG:
            sig = "I"#"J"
        elif component_type_class == TC_FLOAT:
            sig = "F"
        elif component_type_class == TC_DOUBLE:
            sig = "D"
        elif component_type_class == TC_TYPE:
            sig = "com.sun.star.uno.Type"
        elif component_type_class == TC_ENUM:
            sig = component_idl_class.getName()
        elif component_type_class == TC_HYPER:
            sig = "J"
       
        return Class.forName("[" * (dimension - 1) + sig)
   
    def unwrap_for_idl(self, idl_class, value):
        type_class = idl_class.getTypeClass()
        if type_class == TC_INTERFACE or type_class == TC_STRUCT:
            if isinstance(value, Wrapper):
                return value.get_uno_object()
            else:
                # object like a listener and unwrapped one
                return value
        elif type_class == TC_SEQUENCE:
            seq = self.unwrap_sequence(idl_class.getComponentType(), value)
            return array(seq, self.get_type_for_array(idl_class))
        #elif isinstance(value, Any):
            # ToDo
        #    return value
        else:
            return value
   
    def parse_arguments(self, idl_method, args):
        param_idl_classes = idl_method.getParameterTypes()
       
        ret_args = []
        for p, value in zip(param_idl_classes, args):
            ret_args.append(self.unwrap_for_idl(p, value))
        return ret_args
   
    def wrap_prepare_sequence(self, idl_class, args):
        carg = []
        try:
            for v in args:
                if isinstance(v, list) or isinstance(v, tuple) or isinstance(v, _array):
                    carg.append(self.wrap_prepare_sequence(idl_class, v))
                else:
                    carg.append(self.wrap_for_idl(idl_class, v))
            return carg
        except Exception, e:
            print(e)
            return args
   
    def get_component_type(self, idl_class):
        component_idl_class = idl_class
        _idl_class = None
        while True:
            _idl_class = component_idl_class.getComponentType()
            if _idl_class:
                component_idl_class = _idl_class
            else:
                break
        return component_idl_class
   
    def wrap_sequence(self, idl_class, seq):
        component_idl_class = self.get_component_type(idl_class)
        component_type_class = component_idl_class.getTypeClass()
        if component_type_class == TC_INTERFACE or \
            component_type_class == TC_STRUCT or component_type_class == TC_ANY:
            return self.wrap_prepare_sequence(component_idl_class, seq)
        else:
            return seq
   
    def wrap_for_idl(self, idl_class, value):
        type_class = idl_class.getTypeClass()
        if type_class == TC_INTERFACE:
            return Wrapper(value)
        elif type_class == TC_STRUCT:
            return Wrapper(value)
        elif type_class == TC_SEQUENCE:
            # check the type of the content
            return self.wrap_sequence(idl_class.getComponentType(), value)
        elif type_class == TC_ANY:
            if isinstance(value, UnoAny):
                if value.getType().getTypeClass() == TC_INTERFACE:
                    return Wrapper(value.getObject())
                else:
                    return value.getObject()
            else:
                return value
        else:
            return value
   
    def parse_return_value(self, idl_method, value, out_index, out_param):
        ret = self.wrap_for_idl(idl_method.getReturnType(), value)
       
        if len(out_index[0]) == 0:
            return ret
        else:
            params = [ret]
            param_idl_classes = idl_method.getParameterTypes()
            for i, v in zip(out_index[0], out_param[0]):
                params.append(self.wrap_for_idl(param_idl_classes[i], v))
            return params


_runtime = None

def wrap_context(ctx):
    global _runtime
    if not _runtime:
        _runtime = Runtime(ctx)
    return Wrapper(ctx)


from java.lang import Class
from jarray import array
from array import array as _array

class Callable(object):
    """ For method to call. """
    def __init__(self, name, inv):
        self._name = name
        self._inv = inv
   
    def __str__(self):
        return "<Callable <%s>>" % self._name
   
    def __call__(self, *args, **kwargs):
        """ Call method of UNO object through invocation bridge. """
        inv = self._inv
        name = self._name
       
        out_index = array([[]], Class.forName("[S"))
        out_param = array([[None]], Class.forName("[Ljava.lang.Object;"))
       
        idl_method = inv.getIntrospection().getMethod(name, MC_ALL)
        # check length of arguments
        if len(idl_method.getParameterInfos()) != len(args):
            raise KeyError(name + " takes exactly %s arguments (%s given)" %
                           (len(idl_method.getParameterInfos()), len(args)))
        try:
            arguments = _runtime.parse_arguments(idl_method, args)
            ret = inv.invoke(name, arguments, out_index, out_param)
            return _runtime.parse_return_value(idl_method, ret, out_index, out_param)
        except Exception, e:
            raise e



class Wrapper(object):
    """ Wrapper for UNO interface.
    """
    def __init__(self, uno_obj):
        if isinstance(uno_obj, UnoAny):
            uno_obj = uno_obj.getObject();
        obj_type = get_type(uno_obj)
        type_class = obj_type.getTypeClass()
        if not (type_class == TC_INTERFACE or type_class == TC_STRUCT):
            raise TypeError("Illegal UNO object has been passed to Wrapper: %s" % obj_type.getTypeName())
       
        object.__setattr__(self, "_obj", uno_obj)
        inv = _runtime.create_invocation(uno_obj)
        object.__setattr__(self, "_inv", inv)
   
    def get_uno_object(self):
        """ Returns wrapped UNO object. """
        return object.__getattribute__(self, "_obj")
   
    def _get_invocation(self):
        return object.__getattribute__(self, "_inv")
   
    def __str__(self):
        return "<Wrapper <%s>>" % object.__getattribute__(self, "_obj")
   
    __repr__ = __str__
   
    def __dir__(self):
        infos = object.__getattribute__(self, "_inv").getInfo()
        return [info.aName for info in infos]
   
    def __eq__(self, other):
        if isinstance(other, Wrapper) is False:
            return False
        return object.__getattribute__(self, "_obj") == other._inv
   
    def __ne__(self, other):
        if isinstance(other, Wrapper) is False:
            return True
        return object.__getattribute__(self, "_obj") != other._inv
   
    def __methods__(self):
        infos = object.__getattribute__(self, "_inv").getInfo()
        return [info.aName for info in infos if info.eMemberType == MT_METHOD]
   
    def __members__(self):
        infos = object.__getattribute__(self, "_inv").getInfo()
        return [info.aName for info in infos if info.eMemberType == MT_PROPERTY]
     
    def __getattribute__(self, name):
        """ To get property value and callables of methods. """
        #log("get propertyvalue: " + name)
        inv = object.__getattribute__(self, "_inv")
        if inv.hasMethod(name):
            return Callable(name, inv)
        elif inv.hasProperty(name):
            # write-only property should be considered?
            info = inv.getInfoForName(name, True)
            value = inv.getValue(name)
            type_class = info.aType.getTypeClass()
            if isinstance(value, UnoAny) or type_class == TC_INTERFACE or type_class == TC_STRUCT:
                return _runtime.wrap_for_info(info, value)
            else:
                return value
        else:
            if name == "__members__" or name == "__methods__":
                return object.__getattribute__(self, name).__call__()
            return object.__getattribute__(self, name)
   
    def __setattr__(self, name, value):
        """ To set property value. """
        #log("set PropertyValue: " + name)
        inv = object.__getattribute__(self, "_inv")
        if inv.hasProperty(name):
            try:
                info = inv.getInfoForName(name, True)
                if info.PropertyAttribute & PA_READONLY:
                    raise PropertyVetoException("Property is readonly: " + name)
                if info.aType.equals(value):
                    inv.setValue(name, value)
                else:
                    v = _runtime.unwrap_for_info(info, value)
                    inv.setValue(name, v)
            except CannotConvertException, e:
                raise IllegalArgumentException("Unknown property: " + name)
            except Exception, e:
                raise e
        else:
            object.__setattr__(self, name, value)



The coonection part of the code has been separated in Connector.py.
Code:
import uno
from UnoWrapper import wrap_context
from com.sun.star.comp.helper import Bootstrap
from com.sun.star.bridge import XUnoUrlResolver
from com.sun.star.connection import NoConnectException
from com.sun.star.uno import XComponentContext

xctx = None

def bootstrap(officePath="soffice", connectionType="socket", **keys):
    """ Bootstrapping OpenOffice.org and connect to it.
    """
    global xctx
    if xctx: return wrap_context(xctx)
   
    if "args" in keys and "url" in keys:
        args = keys["args"]
        url = keys["url"]
    else:
        if connectionType == "socket":
            tcpDelay = keys.get("tcpNoDelay", "0")
            host = keys.get("host", "localhost")
            port = keys.get("port", "2002")
            args = "-accept=socket,host=%s,port=%s,tcpNoDelay=%s;urp;StarOffice.ServiceManager" % (host, port, tcpDelay)
            url = "uno:socket,host=%s,port=%s,tcpNoDelay=%s;urp;StarOffice.ComponentContext" % (host, port, tcpDelay)
        elif connectionType == "pipe":
            pipeName = keys.get("name", "jythonpipe")
            args = "-accept=pipe,name=%s;urp;StarOffice.ServiceManager" % pipeName
            url = "uno:pipe,name=%s;urp;StarOffice.ComponentContext" % pipeName
        else:
            raise ValueError("unknown connection type: " + connectionType)
   
    ctx = None
    from time import sleep
    from subprocess import Popen
   
    for i in range(60):
        try:
            ctx = connect(url)
        except NoConnectException:
            try:
                pid = Popen([officePath, args]).pid
            except OSError:
                raise Exception("no office executable found: " + officePath)
            sleep(1)
        if ctx:
            return ctx
    return ctx


def connect(url):
    """ Connect to OpenOffice.org and returns wrapped ComponentContext. """
    global xctx
    if xctx: return wrap_context(xctx)
   
    try:
        localctx = Bootstrap.createInitialComponentContext(None)
        resolver = localctx.getServiceManager().createInstanceWithContext(
                      "com.sun.star.bridge.UnoUrlResolver", localctx)
        xResolver = uno.query(XUnoUrlResolver, resolver)
        ctx = xResolver.resolve(url)
       
        xctx = uno.query(XComponentContext, ctx)
        return wrap_context(ctx)
    except Exception, e:
        raise e




The wrapper is not well tested.


Last edited by hanya on Fri Aug 19, 2011 5:15 am; edited 2 times in total
Back to top
View user's profile Send private message
mrodent33
Power User
Power User


Joined: 06 Nov 2010
Posts: 74

PostPosted: Sat Aug 13, 2011 12:22 am    Post subject: Reply with quote

Thanks!

Wow... I will definitely get around to experimenting with this in due course.

By the way I have just learnt that you are the person behind MRI, which I use all the time and without which it would be pretty impossible to do any OOo programming at all. So thanks for that too.
Back to top
View user's profile Send private message
hanya
Super User
Super User


Joined: 04 May 2005
Posts: 543
Location: Japan

PostPosted: Sat Aug 13, 2011 1:46 am    Post subject: Reply with quote

I found the problem about [out] type arguments which is called through Jython.

The first argument of parseStrict method is [inout] type in following codes.
In OOo Basi, the result is "Hoge".
Code:
Sub URLTransformerExample
  aURL = CreateUnoStruct("com.sun.star.util.URL")
  aURL.Complete = ".uno:Hoge"
  CreateUnoService("com.sun.star.util.URLTransformer").parseStrict(aURL)
 
  msgbox aURL.Path
End Sub

This kind of medhod is used like the following in Java:
Code:
URL url = new URL();
         url.Complete = complete;
         URL[] var = new URL[1];
         var[0] = url;
         try {
            UnoRuntime.queryInterface(
                  XURLTransformer.class,
                  m_xContext.getServiceManager()
                        .createInstanceWithContext("com.sun.star.util.URLTransformer",
                              m_xContext)).parseStrict(var);
            URL completed = var[0];

The out value of the first argument should be returned as a first element of the passed array.

In Jython, resulted Path is empty string means parsed value is not set to the first argument of the array:
Code:
from com.sun.star.util import XURLTransformer

def check_in_arguments2():
    url = URL()
    url.Complete = ".uno:Hoge"
   
    wctx = XSCRIPTCONTEXT.getComponentContext()
    ctx = uno.query(XComponentContext, wctx.getUnoObject())
   
   
    smgr = ctx.getServiceManager()
    t = smgr.createInstanceWithContext("com.sun.star.util.URLTransformer", ctx)
    transformer = uno.query(XURLTransformer, t)
    a = [url]
    d = transformer.parseStrict(a)
    print(d) ' True
    print(a) ' css.util.URL
    print(a[0].Path) ' Hoge if parsed but empty string


It seems we have to write a wrapper in Java for correct use.
Back to top
View user's profile Send private message
hanya
Super User
Super User


Joined: 04 May 2005
Posts: 543
Location: Japan

PostPosted: Sat Aug 13, 2011 2:50 am    Post subject: Reply with quote

I need to use array:
http://wiki.python.org/jython/UserGuide#java-arrays
Back to top
View user's profile Send private message
mrodent33
Power User
Power User


Joined: 06 Nov 2010
Posts: 74

PostPosted: Sun Aug 14, 2011 12:16 am    Post subject: Reply with quote

you're a genius!

I copied your code and it ran straight out of the box...

I don't understand the point you are making in the last 2 posts - are there some changes I need to make... ? Maybe to cope with particular cases? If you have time perhaps you might like to try to explain... My understanding of Jython/Python issues is very rudimentary as yet...

but other than that... Thanks so much
Back to top
View user's profile Send private message
hanya
Super User
Super User


Joined: 04 May 2005
Posts: 543
Location: Japan

PostPosted: Sun Aug 14, 2011 1:20 am    Post subject: Reply with quote

Quote:
I need to use array:
http://wiki.python.org/jython/UserGuide#java-arrays
The invoke method of css.script.XInvocation can be called like the following:
Code:

from java.lang import Class
from jarray import array

class Callable(object):
    def __init__(self, name, inv):
        self._name = name
        self._inv = inv
   
    def __call__(self, *args, **kwargs):
        """ Call method of UNO object through invocation bridge. """
        inv = self._inv
        name = self._name
       
        outIndex = array([[]], Class.forName("[S"))
        outParam = array([[None]], Class.forName("[Ljava.lang.Object;"))
       
        try:
            idlMethod = inv.getIntrospection().getMethod(name, MC_ALL)
            arguments = _parseArguments(idlMethod, args)
            ret = inv.invoke(name, arguments, outIndex, outParam)
            return _parseReturnValue(idlMethod, ret, outIndex, outParam)
        except Exception, e:
            raise e


I found some problems in the above wrapper, please forget it. The problems are depends on the invoke method and this kind of problem is well known. If the method takes css.uno.Any type of argument, the implementation (of the API) convert its value to correct and desired value. In the case of the loosely typed language like Python/Jython and so on, we needs a mechanism to pass the value with the type of the value. The uno.Any class is used in PyUNO for this purpose.

Quote:
I don't understand the point you are making in the last 2 posts - are there some changes I need to make... ?
I need to rewrite it.
Quote:
Maybe to cope with particular cases? If you have time perhaps you might like to try to explain...
UNO IDL supports three kind of argument types, in, out and inout. Python language does not support "out" type argument but we need to use it with UNO API. Java does not support it also and out value for an argument requires array which keeps out value after the method call. This influence Jython, read Jython document mentioned above.

If I have a chance to use the wrapper, I would it complete.
Back to top
View user's profile Send private message
mrodent33
Power User
Power User


Joined: 06 Nov 2010
Posts: 74

PostPosted: Sun Aug 14, 2011 2:26 am    Post subject: Reply with quote

... but... is it then still possible to use your MRI inspector?

Code:
# remoteContext = BootstrapSocketConnector.bootstrap(oooExeFolder)
remoteContext = UnoWrapper.bootstrap(oooExeFolder + "soffice.exe", port="2083" )
import hanyaExample
XSCRIPTCONTEXT = hanyaExample.ScriptContext( remoteContext )
remoteServiceManager = remoteContext.getServiceManager()
# OOoUtils.inspectWithCompCxt( remoteServiceManager, remoteContext )
OOoUtils.inspectWithCompCxt( remoteServiceManager, XSCRIPTCONTEXT.getComponentContext() )


with the commented-out stuff I was able to get the inspector showing me the guts of remoteServiceManager... but with the UnoWrapper bootstrap (using both of the "inspect" lines here) I'm getting
"TypeError: inspectCompContext(): 2nd arg can't be coerced to com.sun.star.uno.XComponentContext"...

is there a way of getting a real XComponentContext? is there a way of
using MRI? If no to the latter, how can I find out what interfaces are exported?

later:
just saw your last post... you say you need to rewrite... but it appears to be working fine to me... (so far!)
Back to top
View user's profile Send private message
hanya
Super User
Super User


Joined: 04 May 2005
Posts: 543
Location: Japan

PostPosted: Sun Aug 14, 2011 4:29 am    Post subject: Reply with quote

Quote:
with the commented-out stuff I was able to get the inspector showing me the guts of remoteServiceManager... but with the UnoWrapper bootstrap (using both of the "inspect" lines here) I'm getting
"TypeError: inspectCompContext(): 2nd arg can't be coerced to com.sun.star.uno.XComponentContext"...

is there a way of getting a real XComponentContext? is there a way of
using MRI? If no to the latter, how can I find out what interfaces are exported?
You can not pass the wrapped object to the method of un-wrapped object. You can get the real interface by getUnoObject method of Wrapper class.
Back to top
View user's profile Send private message
mrodent33
Power User
Power User


Joined: 06 Nov 2010
Posts: 74

PostPosted: Sun Aug 14, 2011 1:34 pm    Post subject: Reply with quote

works!

if you ever rewrite this Wrapper thing and make it better (although as I say it seems to be working OK so far), please post on this site
Back to top
View user's profile Send private message
hanya
Super User
Super User


Joined: 04 May 2005
Posts: 543
Location: Japan

PostPosted: Fri Aug 19, 2011 5:20 am    Post subject: Reply with quote

I rewrote the wrapper and the code written above has been updated.
- I rename getUnoObject method to get_uno_object.
- The connection part of the code has been separeted in Connector.py.

There might be some problems remained. I have noticed them:
- calling method which takes type of multi dimensional sequence of any type
- adapter for listeners should be provided
Back to top
View user's profile Send private message
mrodent33
Power User
Power User


Joined: 06 Nov 2010
Posts: 74

PostPosted: Fri Aug 19, 2011 5:52 am    Post subject: Reply with quote

thanks... could you tell me how to get hold of your rewritten code? I tried going to your website but couldn't see where your new code might be.

In the mean time I've added a simple utility method which is not addressed at you, obviously, but to any new users there may be of Jython-OOo (although it may be that we are the only 2 such users in the world...).

This code snippet is here:
http://www.oooforum.org/forum/viewtopic.phtml?p=440494#440494
- it's very simple: you can submit either an object which is hopefully a UNO object, or a Wrapper wrapping one, as the object for introspection, and you can submit either an XComponentContext, or a Wrapper wrapping one, as the other param.

Also, a question concerning Callable "inner class" as used in Wrapper...: in Java, a Callable's call() method can detect and respond to Exceptions occurring inside it... but at present your code appears to swallow Exceptions which are raised by the methods of the wrapped classes... I realise that your use of this Callable inner class occurs in the following block

Code:
    def __getattribute__(self, name):
        """ To get property value. """
        inv = object.__getattribute__(self, "_inv")
        #print(inv.hasMethod(name))
        if inv.hasProperty(name):
            # treats UNO property
            value = inv.getValue(name)
            if isinstance(value, Any):
                return _parseAnyValue(value)
            else:
                return value
        elif inv.hasMethod(name):
            return Callable(name, inv)


... and what you are doing here is so far beyond my abilities, even in Java, let alone in Jython, that I have absolutely no idea whether invocation of __getattribute__ in a way which is responsive to Exceptions inside __call__ is feasible or completely impossible.

The consequence of not being able seems to be:
- that one has to be careful to put try: ... except: blocks inside all the methods of classes which are going to be wrapped... (i.e. instead of relying on Python's excepthook, which I've just discovered)... so it's a minor thing... I was just wondering whether this is possible or not...
- (I think...) that one has to avoid subclassing too much: I'm very much at the testing stage with this one... it may be that these errors (throwing of com.sun.star.lang.DisposedException) is due to an incorrect use by my code of wrapped/non-wrapped objects... and my suspicion is that because a UNO Exception is thrown that this is not a problem inherent to the Jython code itself...
Back to top
View user's profile Send private message
mrodent33
Power User
Power User


Joined: 06 Nov 2010
Posts: 74

PostPosted: Wed Aug 24, 2011 10:10 am    Post subject: Reply with quote

Hi again,

Re: your updated code... (of 2011-08-19)

Thanks... but I got an Exception on this line of code in my program
Code:
desktop.loadComponentFromURL(formDocURL, "_default", 0, None)


... Exception was
CannotConvertException: com.sun.star.script.CannotConvertException: conversion not possible!

The culprit turned out to be this line in your UnoWrapper.Callable.__call__:
Code:
ret = inv.invoke(name, arguments, out_index, out_param)


The basic problem is that for some reason that invoke() doesn't like the fact that the last argument here is "None".
I tried tweaking your code a bit (e.g. missing out the last parameter in "arguments")... but not surprisingly this didn't work...
Back to top
View user's profile Send private message
hanya
Super User
Super User


Joined: 04 May 2005
Posts: 543
Location: Japan

PostPosted: Fri Aug 26, 2011 7:36 am    Post subject: Reply with quote

Code:
doc = desktop.loadComponentFromURL("private:factory/scalc", "_blank", 0, ())
Do not pass None for the argument which takes array type in Java.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    OOoForum.org Forum Index -> OpenOffice.org Macros and API All times are GMT - 8 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group