[Libreoffice] candidate for a new python section in SDK examples page

Lionel Elie Mamane lionel at mamane.lu
Wed Dec 7 14:44:44 PST 2011


On Wed, Dec 07, 2011 at 08:04:14PM +0000, Michael Meeks wrote:

> On Wed, 2011-12-07 at 17:07 +0100, Miklos Vajna wrote:
>> On Wed, Dec 07, 2011 at 03:49:10PM +0000, Michael Meeks <michael.meeks at suse.com> wrote:

>>> 	mod = __import__ ( "actual python-module-name" )
>>>       implHelper = mod.__dict__.get( "g_ImplementationHelper" , None )

>>> 	is supposed to work, or indeed any half-way decent documentation on
>>> what the object is that __import__ returns

> 	So - I know what __import__ is meant to do - but it appears to
> return an entirely useless object; one that has nothing even
> slightly helpful associated with it that would let me find an
> associated member variable.

We seem to have a deep, deep chasm, because things that are natural /
intuitive to me seem to be completely misunderstood by you. I think
that is because I'm of a programming culture that Python took a *lot*
of inspiration from: higher-order functional programming, of which the
"dynamically typed" (which you call "untyped") is a major subculture
(as in Lisp, Scheme & friends).

So, let's try to get to an understanding.

The core thing to understand is that a function is not in any way a
"special" category. It is just a value that can be applied, that can
"consume" other values. Application is just one of the operations,
just like '+' or '^' is just one of the operations.

And you know what? A type is also just a value. Try:
 t = type('a')
And obviously "type(t)".

Having said that preamble, a module is a namespace. That is a mapping
from names to values. You see how that is isomorphic to a dictionary,
which is the Python "basic type" for "mapping", a bit like std::map
for C++'s STL?

So, it is quite natural (in the Python approach) that a module is just
a wrapper around a dictionary.

The module namespace defines name FOO if and only if the underlying
dictionary has a mapping (a value) for key FOO.

You want to know whether module m defines name FOO?
"hasattr(m, 'FOO')" will tell you. Either True or False. You want to
*get* the value of name foo in m? "getattr(m, 'FOO')" or m.FOO if FOO
is a source-code constant. You want to do both in one operation?
f = m.__dict__.get('FOO', BAR)
f will have the value of 'FOO' in m's namespace, or BAR if 'FOO' is
not bound by m. None is a good choice for BAR...

But I get the impression that you know that, so that I'm not sure what
is your issue or question. Let's continue...

>> Second line:
> ...
>> implHelper = mod.__dict__.get( "g_ImplementationHelper" , None )
> ...
>> In short, it checks if there is a funcion named "g_ImplementationHelper"
>> in "actual python-module-name".

> 	Riiight ;-) 'function' or 'object' or ... it is all so
> un-typed and meta, it could do almost anything;

It is a value. Which could be an integer, a string, a function,
whatever. Either you just use it as you expect it to be (and an
exception/error is raised if that fails), or you are cautious and you
check that it has the right structure before using it. I thought you
wanted g_ImplementationHelper to be a function, but apparently
not. You want it to have attributes like e.g. 'impls'. So just use
"duck typing" and check if it has the attributes you want:

 if hasattr(implHelper, 'impls'):
    ... OK, continue ...
 else
   ERROR

or

 i = implHelper.__dict__.get('impls')
 if i == None: // or "if i is None"... subtly different...
   ERROR
 ... OK, continue...

or just use it and catch the exception:

 try:
    i=implHelper.impls
 except AttributeError
    raise Uno exception?


If for some reason you don't want to be liberal and use duck typing,
and want to force implHelper to be created by
unohelper.ImplementationHelper() (or a derived class), you can use a
subytping model:

 if not isinstance(i, unohelper.ImplementationHelper):
    ERROR


> On Wed, 2011-12-07 at 18:05 +0100, Lionel Elie Mamane wrote:

>> It is an object of type/class "module". Type module has exactly one
>> member:

>> __dict__ (read-only): the module's namespace as a dictionary
>>   (http://docs.python.org/library/stdtypes.html#typesmapping)

>>   __dict__ is the dictionary of attributes of the object. That is, if
>>   there is no member BAR in object FOO, then FOO.BAR is
>>   FOO.__dict__["BAR"]

>> __dict__ is prepopulated by the module loading system with:

> 	Sure -none of these are what I want; I want to hook out any
> g_ImplementationHelper instances that are around.

What is "hook out"? Whatever that is, just get the
g_ImplementationHelper attribute and do whatever you want with it.

>>> let us find an internal variable definition ;-)

>> The code you quoted looks right. I would then continue with:

>>  if inspect.isroutine(implHelper):

> 	The code reliably returned Null to me ;-) for wizards.fax, and for
> wizards.fax.CallWizard.

You mean it returns None? That's strange, it should return either True
or False. Can you give me a way to reproduce getting None from it?

If you mean it returns "False", well, yes, because as I discovered
through Caolán example, g_ImplementationHelper is not supposed to be a
function, but a value with a 'impls' attribute.

>> to test whether implHelper is a function (something that takes
>> arguments and returns a result) as I guess it is expected to be. The
>> inspect module having been loaded, obviously.

> 	Having some nice way to dump all the available methods, and/or classes
> on a module

m.__dict__.keys() gives the set of bound names as a list.

m.__dict__ *is* the mapping of (name,values) pairs; the values can be
classes, functions (methods) or other values: integers, lists,
strings, ... You can iterate over it with it=m.__dict__.iteritems()
(which returns an iterator); main useful member: it.next(), which can
be called through next(it), or next(it, value_for_end_of_sequence) to
avoid raising an exception (StopIteration) at the end.

> that is clearly annotated, and documented,

The documentation of a function is its __doc__ attribute. So if m.foo
is a function, m.foo.__doc__ is its documentation.

> associated by the intrinsic type of the object

"type(m.foo)" returns its formal type, but usually in Python... Duck
typing! So what would you do with the *actual*, formal type of an
object? Additionally, Python's type system (as in types-as-values) is
so weak that it probably won't do what you want...:

class a:
  bar=1

class b:
  foo=2

an_a=a()
a_b=b()

type(a)==type(b) // returns True! Because they are both of type 'instance'...

type(an_a) is *not* a. an_a and a are two values (objects) which are
related by the "is an instance of" relation.


Maybe instead of discussing things in generality, we should dive into
the concrete problem you are having? Give me UNO/LibreOffice
n00b/beginner-proof instructions on how to reproduce the problem.

-- 
Lionel


More information about the LibreOffice mailing list