Python introspection to enlightenment?

Boudewijn Rempt boud at valdyas.org
Wed Jun 14 08:36:52 UTC 2017


On Tue, 13 Jun 2017, Brendan Scott wrote:

> I'm trying to query the attributes of the krita module, krita.Krita and
> krita.Krita.instance() objects to get them to tell me a bit about themselves
> (actually, it looks like I'm inspecting krita.krita.Krita?!). 

Well, we do need to discuss how we should name the various components of 
the python scripting plugin.

We've got:

libkis: the wrapper library that exposes Krita to scripting languages, which has a class called Krita,
that is aliased as Krita, Application or Scripter and forms the main entry for scripting.

Krita.sip: generates a python module called pykrita, which wraps libkis, and provides pykrita and PyKrita.krita

krita: the python module created in plugins/extensions/pykrita/plugin/krita... This provides
the actual built-ins Scripter, Application and Krita.

I am getting confused myself, and would like to make this a bit clearer.


> However, they
> all tell me that they are pyqtWrapperType classes and have a standard set of
> methods:
> 
> standard_methods = ['__add__', '__class__', '__contains__', '__delattr__',
> '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__',
> '__getitem__', '__getnewargs__', '__gt__', '__hash__', '__init__', '__iter__',
> '__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__', '__new__',
> '__reduce__', '__reduce_ex__', '__repr__', '__rmod__', '__rmul__',
> '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'capitalize',
> 'casefold', 'center', 'count', 'encode', 'endswith', 'expandtabs', 'find',
> 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isdecimal', 'isdigit',
> 'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle',
> 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition',
> 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip',
> 'split', 'splitlines', 'startswith', 'strip', 'swapcase', 'title',
> 'translate', 'upper', 'zfill']

If I do in the Scripter:

import krita
print(dir(krita.Krita))

I get the full list of methods, though:

['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattr__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'action', 'actions', 'activeDocument', 'activeWindow', 'addDockWidgetFactory', 'addExtension', 'addProfile', 'batchmode', 'blockSignals', 'childEvent', 'children', 'connectNotify', 'createAction', 'createDocument', 'customEvent', 'deleteLater', 'destroyed', 'disconnect', 'disconnectNotify', 'documents', 'dumpObjectInfo', 'dumpObjectTree', 'dynamicPropertyNames', 'event', 'eventFilter', 'filter', 'filterStrategies', 'filters', 'findChild', 'findChildren', 'fromVariant', 'inherits', 'installEventFilter', 'instance', 'isSignalConnected', 'isWidgetType', 'isWindowType', 'killTimer', 'metaObject', 'moveToThread', 'notifier', 'objectName', 'objectNa
 meChanged', 'openDocument', 'openWindow', 'parent', 'profiles', 'property', 'pyqtConfigure', 'readSetting', 'receivers', 'removeEventFilter', 'resources', 'sender', 'senderSignalIndex', 'setActiveDocument', 'setBatchmode', 'setObjectName', 'setParent', 'setProperty', 'signalsBlocked', 'startTimer', 'staticMetaObject', 'thread', 'timerEvent', 'tr', 'version', 'views', 'windows', 'writeSetting']

> and standard doc strings:
> 
> standard__doc__ = """str(object='') -> str
> str(bytes_or_buffer[, encoding[, errors]]) -> str

Ah -- we probably need to use 

http://pyqt.sourceforge.net/Docs/sip4/directives.html#directive-%Docstring

To add docstring documentation to the pykrita sip wrapper classes.

> 
> Create a new string object from the given object. If encoding or
> errors is specified, then the object must expose a data buffer
> that will be decoded using the given encoding and error handler.
> Otherwise, returns the result of object.__str__() (if defined)
> or repr(object).
> encoding defaults to sys.getdefaultencoding().
> errors defaults to 'strict'.
> """.strip()
> 
> 
> Many of them seem callable, but callable(attribute) returns False for all of
> them. The dumpObjectInfo method of krita.Krita.instance returns None. Does it
> write something somewhere?

To be honest, I don't know...

> 
> I assume that pyqtWrapperType will be created by wrapping some c++ code
> somewhere? How do I discover (other than by looking at the source
> code/existing scripts and making an educated guess?) eg:
> * that the Extension class has a method called setup() that I'm supposed to
> override?
> * whether Extension has any other special methods?
> * what parameters each of the methods of these objects takes?
> 
> The docs say:
>   All classes are based on QObject, so QMetaObject introspection can
>   be used to discover properties, slots and signals and automatically
> expose all functionality to the client.

Ah, that needs to be clarified -- that is more useful for bindings
writers and than script writers. In fact, at one point I had a python
binding implementation that would introspect the libkis classes and
create the python classes from there. That was very fragile, though,
and there were problems with signals.

Right now, the bindings are created with sip.

> It's not clear how to make use of these through Python.



I'm really glad that you're posing all these questions, before we really
release the Python scripting -- it is a big help in getting things right!

-- 
Boudewijn Rempt | http://www.krita.org, http://www.valdyas.org


More information about the kimageshop mailing list