About autocompletion and calltips.

69 views
Skip to first unread message

Edward K. Ream

unread,
Sep 10, 2011, 9:36:01 AM9/10/11
to leo-editor
This thread will summarize everything that users and developers should
know about autocompletion and calltips.

This is intended for general consumption, and I hope it helps Terry
with his project of adding Blender completions to Leo.

Much of the following is "redundant" in the sense that it has appeared
in various places on these forums or in LeoDocs.leo, but the
Autocompletion and Calltips sections of the "Using Leo's Commands"
chapter has not been updated to reflect the new information. This
thread will be pre-writing for the new documentation.

Terminology
=========

There are two basic distinctions:

1. The **legacy** (aka tabbed) completer shows completions in Leo's
tabbed pane. The **qcompleter** shows completions in or near the body
pane.

2. The **codewise completer** uses the codewise wrapper of ctags
data. The **Leo-centric completer** computes the **base object** of a
expression in a Leo file, and uses eval to determine the type of the
base object and thus the possible completions.

Major autocompletion settings
======================

These are found in leoSettings.leo: @settings-->Autocompleter

- @bool use_codewise = False

True: use codewise completions.
False: use Leo-specific completions.

- @bool use_qcompleter = True

True: show completions in a QCompleter popup.
False: show completions in Leo's Completions tab.
This option has effect only when using the qt or qttabs gui's.

There are other settings. They will be discussed later.

That enough for now. Later posts will discuss the following:

- Setting up to use ctags/codewise completion.

- Detailed instructions for using the autocompleter. This will
discuss the effect of several other autocompletion-related settings.

- Documentation of the autocompleter code itself.

Edward

Terry Brown

unread,
Sep 10, 2011, 10:19:22 AM9/10/11
to leo-e...@googlegroups.com
On Sat, 10 Sep 2011 06:36:01 -0700 (PDT)
"Edward K. Ream" <edre...@gmail.com> wrote:

> This thread will summarize everything that users and developers should
> know about autocompletion and calltips.

Excellent, thanks for doing this.

Cheers -Terry

Edward K. Ream

unread,
Sep 12, 2011, 11:08:37 AM9/12/11
to leo-editor
On Sep 10, 8:36 am, "Edward K. Ream" <edream...@gmail.com> wrote:

> Later posts will discuss the following:
>
> - Setting up to use ctags/codewise completion.

This section describes how to use Ville's codewise.py module in leo
\external folder.

**Note**: I've recently made a few changes to codewise.py. The
following discussion reflects the following changes:

- Changed docstring.

- The setup command does not crash if the ~/.ctags file already exist.

- The setup command does not call the init command, and thus does
not delete ~/.codewise.db.

- Revised various print statements so they look better with Python
3.x.

**Important**: Leo's core contains all necessary autocompletion
code. In particular, enable *neither* the ctagscompleter.py
plugin *nor* the codewisecompleter.py plugin. I plan to remove
these plugins immediately, unless someone gives a good reason not
to do so.

**Important**: I've taken care to with the following instructions, but
there could be oversights or misunderstandings. I would appreciate
any
corrections or additions.

Creating codewise/ctags data
============================

1. Make sure you have exuberant ctags (not just regular ctags)
installed. It's an Ubuntu package, so its easy to install if
you're using Ubuntu.

2. Execute the following commands from Leo's external/codewise.py
module. **Note**: On Windows, you can use codewise.bat to
execute these commands. For example::

python <<path to leo>>\leo\external\codewise.py %*

A. [Optional] Create a custom ~/.ctags file containing default
configuration settings for ctags::

codewise setup

This command will leave the ~/.ctags file unchanged if it
exists. Othewise, the ``codewise setup`` command will
create a ~/.ctags file containing the following defaults::

--exclude=*.html
--exclude=*.css

See: http://ctags.sourceforge.net/ctags.html#FILES for more
details about the .ctags file.

B. [Optional] Delete the existing ctags database in
~/.codewise.db::

codewise init

C. Add ctags data to the existing ctags database::

codewise parse <path to directory>

You can add data from multiple sources by running
the ``codewise parse`` command on multiple directories.

To repeat, all comments and corrections are welcome.

Edward

Edward K. Ream

unread,
Sep 12, 2011, 1:24:53 PM9/12/11
to leo-editor
On Sat, Sep 10, 2011 at 8:36 AM, Edward K. Ream <edre...@gmail.com> wrote:

> Later posts will discuss...detailed instructions for using the autocompleter.  This will


> discuss the effect of several other autocompletion-related settings.

Here they are, but first some notes:

1. Notice the dog that is not barking. There is no discussion of the
setting @bool use_codewise because that setting is no longer used!
Indeed, Leo *always* attempts Leo-specific (eval-oriented)
completions, and falls back on codewise (ctags) conversions if there
are none. I'll remove this setting soon from leoSettings.leo.

2. The follow docs are not entirely complete: I'll fold in some
details from the existing docs. However, the following docs discuss
the most important features of autocompletion. A later post will
discuss in detail how the code works.

All corrections an completions welcome. Without further ado, the
following is my best attempt at explaining how autocompletion actually
works...

----------------------------------------------------------------

Leo's autocompletion suggests **completions**, text may be valid in a given
point, or **context** in source code. For example, suppose the context is::

os.path.s

That is, suppose the cursor follows ``os.path.s`` in the body pane. The valid
completions are all the members of Python's os.path module whose names
start with 's',
namely::

samefile
sameopenfile
sep
split
splitdrive
splitext
splitunc
stat
supports_unicode_filenames
sys

Starting autocompletions
========================

There are two ways to have Leo show autocompletions, manually and automatically.
You can use both at the same time.

**Manual autocompletion**: Leo will show autocompletions whenever you execute
the auto-complete-force (ctrl-space) command.

**Automatic autocompletion**: If (automatic) autocompletion is
enabled, Leo will show completions whenever you type a period in the
body pane.

You can enable autocompletion in several ways:

1. By setting @bool enable_autocompleter_initially = True.

2. By using the toggle-autocompleter (Alt-1) command.

Displaying autocompletions
==========================

How Leo displays these completions depends on the setting::

@bool use_qcompleter

True: Leo shows completions in the QCompleter popup window.
False: Leo shows completions in the log pane.

Using the QCompleter
====================

When the ``@bool use_qcompleter`` setting is False, Leo shows all
completions in a
popup window, regardless of how many completions there are. To **accept** a
completion, use the up and down arrows to select a completion, then type the
return key. To **cancel** completion, type the escape key. As an important
shortcut, if the popup window contains only one entry, you may accept a
completion by simply typing the return key.

Using the Log pane completer
============================

When the ``@bool use_qcompleter`` setting is True, Leo shows completions in in
Leo's log pane. When there are more than 20 completions, Leo shows only the
characters that start a completions. For example, when completing ``os.path.``
the log pane will show::

_ 17
a 2
b 1
c 2
d 3
e 4
g 5
i 5
j 1
l 1
n 2
o 1
p 2
r 2
s 10

To see the complete list, type the '!' character. You will see::

__all__
__builtins__
__cached__
__doc__
__file__
__name__
__package__
_get_altsep
_get_bothseps
_get_colon
_get_dot
_get_empty
_get_sep
_get_special
_getfileinformation
_getfinalpathname
_getfullpathname
abspath
altsep
basename
commonprefix
curdir
defpath
devnull
dirname
exists
...

Typically, however, you would simply type one of the valid prefix characters.
For example, typing the letter 'a' would create the context ``os.path.a`` and
the log pane would show::

abspath
altsep

As you type, Leo enters the longest common prefix of all completions into the
body pane. Typing return, escape or ctrl-g (or any other alt or ctrl key) ends
completion.

Showing docstrings
==================

Regardless of the setting of ``@bool use_qcompleter``,
typing '?' during autocompletion will show the docstring of
the present context. For example, suppose the context is
``os.path.join``. Now typing '?' will show::

Join two or more pathname components, inserting "\" as needed.
If any component is an absolute path, all previous path components
will be discarded.

It is not possible to copy the docstring from the log pane
when using the QCompleter because the QCompleter popup window is a modal dialog.

Edward

Kent Tenney

unread,
Sep 12, 2011, 1:27:20 PM9/12/11
to leo-e...@googlegroups.com
> To repeat, all comments and corrections are welcome.

I was confused by the instructions:


> python <<path to leo>>\leo\external\codewise.py %*
>
> A. [Optional] Create a custom ~/.ctags file containing default
> configuration settings for ctags::
>
> codewise setup

I was replacing the % with "codewise setup" ie:
$ python <<path to leo>>\leo\external\codewise.py codewise setup

then I wondered if there should be script in my path named "codewise"

then I figured out that "codewise" was an alias for <path>/codewise.py

I think it would be clearer to me if instead of
codewise setup

I just read
setup

I ran
$python codewise.py setup
$python codewise.py init
$python codewise.py parse my/lib/
$python codewise.py parse leo-editor/leo/core/

next: how to activate completion?
- loaded leoDocs.leo from help menu, did a "nav" on "completer"
- usage instructions were a few pages down

OK, press <ALT 1>, log pane tells me autocomplete is on.

Now it's becoming useful. A few observations.

If I want
leo.core.leoCommands.leoNodes.position

all is well if I type as above: each "." brings up the correct set of choices.

If I type
leoNodes.

I get a list which looks like every known token ...

**THIS JUST IN**

Another message from Edward ... signing off to study it ...

Thanks,
Kent

>
> Edward
>
> --
> You received this message because you are subscribed to the Google Groups "leo-editor" group.
> To post to this group, send email to leo-e...@googlegroups.com.
> To unsubscribe from this group, send email to leo-editor+...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/leo-editor?hl=en.
>
>

Edward K. Ream

unread,
Sep 12, 2011, 1:58:56 PM9/12/11
to leo-e...@googlegroups.com
On Mon, Sep 12, 2011 at 12:27 PM, Kent Tenney <kte...@gmail.com> wrote:

> I was confused by the instructions:
>>        python <<path to leo>>\leo\external\codewise.py %*

Yes. It's surprising how the "easy" stuff isn't.

Still, the main thing is to get python to execute leo/external
codewise.py with a single argument, which is either "setup", "init" or
"parse" (without the quotes :-)

> I was replacing the % with "codewise setup" ie:

%* means all arguments to the script, in this case codewise.bat.
Please translate to the Linux world...

Edward

Edward K. Ream

unread,
Sep 12, 2011, 2:19:41 PM9/12/11
to leo-editor
On Sat, Sep 10, 2011 at 8:36 AM, Edward K. Ream <edre...@gmail.com> wrote:
> This thread...is intended for general consumption, and I hope it helps Terry

> with his project of adding Blender completions to Leo.

I'll continue with more "careful" posts tomorrow, but now that I am
more familiar with the code and settings and what they do (or don't
do), I'd like to "jump ahead" with some ideas that Terry might use
immediately.

The main thing to know is that Leo's autocompleter *always* tries
Leo-specific completions, and then falls back to ctags/codewise
completions using Ville's codewise module to "make sense" of the
unified database ~/.codewise.db. Again, I'll leave the details of the
codewise magic for another post.

Indeed, ac.get_completions, leoPy.leo::

class AutoCompleterClass-->Helpers-->get_completions & helpers

computes the list of completions as follows::

aList = (
self.get_leo_completions(prefix) or
self.get_codewise_completions(prefix)
)

Again, notice the dog that isn't barking: no settings or other
switches are involved.

Let's look at get_leo_completions. In essence, it is just::

d = self.get_leo_namespace(prefix)
aList = self.attr_matches(prefix,d)
aList.sort()

Only ac.get_leo_namespace is of real interest. Here it is::

def get_leo_namespace (self,prefix):

'''Return an environment in which to evaluate prefix.
Add some common standard library modules as needed.'''

k = self.k
d = {'c':k.c, 'p':k.c.p, 'g':g}
aList = prefix.split('.')
if len(aList) > 1:
name = aList[0]
m = sys.modules.get(name)
if m: d[name]= m
return d

Ok, so here is my idea. The blender 'bpy' module is the "root" of all
blender scripting code. Suppose we add something like the following
code (untested) right after the definition of d::

if self.use_blender_completions:
<< add path to blender's python library to sys.path >>
import bpy
d['bpy'] = bpy

Now Leo should be able to recognize the 'bpy' module just like Leo
recognizes the 'c', 'g' and 'p' objects, and the various Python
modules that are added to the context.

Wouldn't this be an easy way to adding support for Blender autocompletions?

**Important**: very likely, one could do something almost as simple in
order to add Blender support using ctags/codewise. The choice might
be arbitrary, or it may turn out that the codewise way is a bit better
in general. However, patching get_leo_namespace can be done quickly
as a prototype.

We might want to generalize the hack to get_leo_namespace by adding
other useful symbols for Blender programming. Not exactly sure what
they are, but whatever they are it should be easy to support them.
Otoh, perhaps the generality of the ctags/codewise approach will make
further hacks moot.

Terry, what do you think?

Edward

Terry Brown

unread,
Sep 12, 2011, 2:28:17 PM9/12/11
to leo-e...@googlegroups.com

I haven't had time to completely digest these posts yet, will try
ctagging blender when I can. But if leo can introspect bpy.* as
effectively as ipython does that kind of thing, or blender's own
autocompletion, then adding bpy as a namespace might be very effective,
I guess it's only a matter of "import bpy".

Of course, that would mean I'd have to use Leo with Python 3.x, which
would mean getting 3.x PyQt installed...

Cheers -Terry

Terry Brown

unread,
Sep 12, 2011, 2:37:45 PM9/12/11
to leo-e...@googlegroups.com
On Mon, 12 Sep 2011 13:28:17 -0500
Terry Brown <terry_...@yahoo.com> wrote:

> Of course, that would mean I'd have to use Leo with Python 3.x, which
> would mean getting 3.x PyQt installed...

Which might be a plus for the codewise approach, seeing I imagine you
can use a codewise database generated with Python 3.x from Leo-Qt-2.x.

Cheers -Terry

Edward K. Ream

unread,
Sep 12, 2011, 3:13:14 PM9/12/11
to leo-e...@googlegroups.com
On Mon, Sep 12, 2011 at 1:28 PM, Terry Brown <terry_...@yahoo.com> wrote:
> On Mon, 12 Sep 2011 13:19:41 -0500
> "Edward K. Ream" <edre...@gmail.com> wrote:
>
>> We might want to generalize the hack to get_leo_namespace by adding
>> other useful symbols for Blender programming.  Not exactly sure what
>> they are, but whatever they are it should be easy to support them.
>> Otoh, perhaps the generality of the ctags/codewise approach will make
>> further hacks moot.
>>

> Of course, that would mean I'd have to use Leo with Python 3.x, which


> would mean getting 3.x PyQt installed...

Why is that? Blender compiles with Python 2.6, iirc.

Edward

Edward K. Ream

unread,
Sep 12, 2011, 3:50:51 PM9/12/11
to leo-editor


On Sep 12, 1:28 pm, Terry Brown <terry_n_br...@yahoo.com> wrote:

> If leo can introspect bpy.* as effectively as ipython does that kind of thing, or blender's own
> autocompletion, then adding bpy as a namespace might be very effective,
> I guess it's only a matter of "import bpy".

Hmm. The bpy module imports _bpy, which is a Blender builtin.

It might be in Blender/python32.dll...

Edward

Terry Brown

unread,
Sep 12, 2011, 4:13:21 PM9/12/11
to leo-e...@googlegroups.com
On Mon, 12 Sep 2011 14:13:14 -0500
"Edward K. Ream" <edre...@gmail.com> wrote:

> > Of course, that would mean I'd have to use Leo with Python 3.x, which
> > would mean getting 3.x PyQt installed...
>
> Why is that? Blender compiles with Python 2.6, iirc.

Blender 2.5x requires Python 3.x, I'm fairly sure, not positive.

Cheers -Terry

Edward K. Ream

unread,
Sep 12, 2011, 4:30:03 PM9/12/11
to leo-editor
On Sep 12, 3:13 pm, Terry Brown <terry_n_br...@yahoo.com> wrote:

> Blender 2.5x requires Python 3.x, I'm fairly sure, not positive.

Ah. Blender 2.5x is *built* with Python 3.x. That's important ;-)

So now the trick is to load the bpy module and/or the builtin _bpy
module **from Leo**.

Here is the first step::

import ctypes
m = ctypes.windll.LoadLibrary(r'C:\apps\Blender\python32.dll')
print(m)
print(m.Py_Initialize)
print(m.PyImport_ImportModule)

And here is the output::

<WinDLL 'C:\apps\Blender\python32.dll', handle 7a40000 at 4852550>
<_FuncPtr object at 0x047ABE40>
<_FuncPtr object at 0x047ABEB8>

So this is a fun puzzle...solvable, I hope, using Python's ctypes
module...

Presumably, similar code will work on Linux.

Edward

Edward K. Ream

unread,
Sep 12, 2011, 6:44:23 PM9/12/11
to leo-editor
On Sep 12, 3:30 pm, "Edward K. Ream" <edream...@gmail.com> wrote:

> So this is a fun puzzle...solvable, I hope, using ctypes...

This is a ton of fun. Here is the latest script.

**Warning**: This script must be run with Python 3.x: it will crash
Python 2.x.

import ctypes
m = ctypes.PyDLL(r'C:\apps\Blender\python32.dll')
m.Py_Initialize()

# Import imp.
s = ctypes.c_char_p(b'imp')
m.PyImport_ImportModule.restype = ctypes.py_object
o = m.PyImport_ImportModule(s)
print(o

And here is the output::

<module 'imp' (built-in)>

o is **Blender's** imp module, as can be seen by comparing id(o) with
id(imp), where imp is Python's "regular" (not-embeded in Blender) imp
module.

The key to the entire puzzle is the assignment::

m.PyImport_ImportModule.restype = ctypes.py_object

which is effectively a cast from int to PyObject*. This is buried
deep in the docs:

http://docs.python.org/library/ctypes.html#ctypes-fundamental-data-types-2

With this cast in place, we can treat o *exactly* as if we had
imported imp from Blender's internal Python compiler.

Now the door is unlocked. We can import sys in the same way, add
paths to sys.path, and use the *embedded* imp module to load the 'bpy'
module. If all goes as expected, the bpy should be able to import the
'_bpy' module. Stay tuned...

Edward

Edward K. Ream

unread,
Sep 12, 2011, 10:27:11 PM9/12/11
to leo-editor
On Mon, Sep 12, 2011 at 5:44 PM, Edward K. Ream <edre...@gmail.com> wrote:

> Now the door is unlocked.  We can import sys in the same way, add
> paths to sys.path, and use the *embedded* imp module to load the 'bpy'
> module.  If all goes as expected, the bpy should be able to import the
> '_bpy' module.  Stay tuned...

Alas, not so. The problem is that Blender's init logic creates the
_bpy module, and to do that essentially all of Blender's init logic
must already have taken place.

The init logic consists of main() in creator.c, BPY_python_start() in
bpy_interface.py, and BPy_init_modules() in bpy.c. This is extremely
complicated code: it's out of the question to try to duplicate the
code from Python using ctags. Furthermore, even if we could run main()
from Python, it's not at clear that we could then access the *inited*
modules from the DLL's.

One could well imagine a Python bridge into Blender, but that bridge
must be created by *C* code. It is just barely possible that the
bridge already exists, but I haven't seen any evidence of it yet.

In short, it's unlikely that we can base the autocompletion on a
properly imported bpy module. We *can* still provide support for
Blender-oriented autocompletion in Leo, but it looks like we shall
have to use codewise to do it. Even this way may not be trivial--we
may have to use dummy description files to drive ctags.

Edward

Edward K. Ream

unread,
Sep 12, 2011, 10:38:29 PM9/12/11
to leo-editor
On Mon, Sep 12, 2011 at 9:27 PM, Edward K. Ream <edre...@gmail.com> wrote:

> Furthermore, even if we could run main() from Python, it's not at clear that we could then access the *inited* modules from the DLL's.

This is a fascinating puzzle. Python's C API is tantalizing, but at
present I see no way to use it to create a proper Leo/Blender bridge.

Suppose we start blender *from Leo* by calling main(). Is there a way
to use a C API call to get access to the *properly inited* bpy (or
_bpy module)? I rather think not.

True, we can use the C API to run Python code using the embedded
Python interpreter, but that Python code will *not* run in the
environment created by main(!). In other words, the Python code
embedded in Blender does not, in fact, have access to the Blender's
data...

It's frustrating: it would be relatively simple to create (in C) a way
for *external* Python programs to gain access to the *properly inited*
Blender environment. The itsy-bitsy detail is that the C code doesn't
seem to exist.

However, it is just barely possible that there *do* exist one or more
access functions (or even variables) that would, say, allow access to
sys.modules *after* it has been inited by main() and its
helpers...I'll be looking for those bridges tomorrow.

Edward

Edward K. Ream

unread,
Sep 13, 2011, 8:32:39 AM9/13/11
to leo-editor
On Mon, Sep 12, 2011 at 9:38 PM, Edward K. Ream <edre...@gmail.com> wrote:

> This is a fascinating puzzle.  Python's C API is tantalizing, but at
> present I see no way to use it to create a proper Leo/Blender bridge.

Warning: this post is more geeky than I imagined for this thread.
Those not interested in gory details should skip it. I'll get back to
documenting autocompletion later, I promise. But not just yet, I'm
having too much fun :-)

Late last night I saw why this project is doomed, at least for the
moment. I had spent hours using an evaluation copy of PE Explorer,
http://www.heaventools.com/overview.htm, looking for all the C
functions I had found in the Blender sources. But I could not find
most of them in the export tables of blender.exe or python32.dll or
anywhere else.

Suddenly it occurred to me that just because a function was visible to
other C *functions* (the function wasn't static) did not mean that the
function had to be visible to other *DLLs*. Thus, most functions will
appear in *none* of the export tables in any of the DLLs. Doh!
Indeed, much of the code is "hidden" inside blender.exe. For example,
the main function is visible only as the entry point into blender.exe.

This means that most (all?) of the functions needed to init blender
simply will not be available via Python's ctypes module. End of
project. Still, it was a lot of fun looking at a major project from
the DLL point of view. And I learned more about calling sequences
than I ever dreamed there was too learn: See
http://en.wikipedia.org/wiki/X86_calling_conventions

All is not lost, however. As part of my explorations into the nooks
and crannies of the Blender *sources*, I found
blender/intern/bpy_introspect_ui.py. The comment at the head of the
file is::

# This script dumps ui definitions as XML.
# useful for finding bad api usage.

# Example usage:
# python intern/tools/bpy_introspect_ui.py

I haven't studied the code, but something like this, when run from
**inside** Blender (from the Blender console) could produce a
pure-python version of a "dummy" version of the bpy module and its
sub-modules bpy.data, bpy.ops, bpy.props, bpy.types, bpy.context,
bpy.utils. The same trick could be applied to the real (??) modules
bgl, blf, and mathutils.

After running the script, we simply make the dummy modules part of
Leo. We can then use *either* the eval-based approach or the
codewise-based approach to autocompletion.

This is good news. I've written lots of scripts like this. It can be
written inside Leo and imported into Blender by hand. It doesn't have
to be particularly easy to do the import: conceptually, the script
will only be run once. I'll start work on this project today...

Edward

P.S. But wait a minute! bpy_introspect_ui.py is to be run
**outside** of Blender!! What the heck is going on??

Hmm. There is a fake_main function that "creates" lots (all?) of
(fake?) instances of bpy.types, bpy.props, bpy.data, bpy.utils,
bpy.app and bpy.path.

Hahaha. After creating the fake bpy module, the script *imports* it.
It can then do some (fairly mysterious) manipulations that allow it to
create the xml file.

So the next step will be to run bpy_introspect_ui as a *Leo script*
with sys.path set up to appear to be run in
<blender-sources>/blender/intern. I can then study the script under a
microscope, clear up all its mysteries, and use it, maybe mostly
unchanged, to create the desired dummy Python modules. It looks like
a completely doable project.

EKR

Edward K. Ream

unread,
Sep 13, 2011, 11:31:44 AM9/13/11
to leo-editor
On Tue, Sep 13, 2011 at 7:32 AM, Edward K. Ream <edre...@gmail.com> wrote:

> So the next step will be to run bpy_introspect_ui as a *Leo script*

Actually, bpy_introspect_ui.py appears to be a bit out of date. So
to reduce the amount of change, I am running it "in place".

I'm having great fun bringing it up to snuff as follows:

- The folder release/scripts/ui does not exist.
release/scripts/startup/bl_ui looks like a likely replacement.

- Added several new dummy classes so that the imports in
release/scripts/startup/bl_ui/*.py work

- Added several directories to sys.path

This is pretty much run-the-script-until-it-fails-then-hack-the-script approach.

Much like the conversion to Python 3k...

Oh yes, one more thing. Right next to the call to print(self.layout._as_xml())
there is a commented-out call to print(self.layout._as_python()).
Couldn't get much easier...

Edward

Edward K. Ream

unread,
Sep 13, 2011, 12:31:02 PM9/13/11
to leo-editor
On Tue, Sep 13, 2011 at 10:31 AM, Edward K. Ream <edre...@gmail.com> wrote:

> Actually,  bpy_introspect_ui.py appears to be a bit out of date.  So
> to reduce the amount of change, I am running it "in place".

The modified script now runs to completion. Alas, it produces pretty
incomprehensible output.

Perhaps I can figure out how to make it do what I want, but that would
require actually understanding what it does ;-) I'll try now to
actually make sense of it using dumps of various kinds...

The alternative would be to run an introspection script from within
Blender itself. The script would use Python's inspect module to
gather all needed info about the modules we care about (the ones
mentioned when Blender's console starts up). The script would then
write dummy module definitions. Clearly, this script should be easier
to write than, say, jEdit2py...

Edward

Edward K. Ream

unread,
Sep 13, 2011, 12:50:24 PM9/13/11
to leo-editor
On Sep 13, 11:31 am, "Edward K. Ream" <edream...@gmail.com> wrote:

> The modified script now runs to completion.  Alas, it produces pretty
> incomprehensible output.
>
> Perhaps I can figure out how to make it do what I want, but that would
> require actually understanding what it does ;-) I'll try now to
> actually make sense of it using dumps of various kinds...

This has no chance of working--the script creates dummy classes which
are of no value for autocompletion.

It's time for a new approach, namely creating autocompletion info
(dummy blender classes and methods) using a script that runs within
the Blender console. This will give us the definitive version of bpy
and all the other modules of interest.

Edward

Terry Brown

unread,
Sep 13, 2011, 1:33:40 PM9/13/11
to leo-e...@googlegroups.com
On Tue, 13 Sep 2011 09:50:24 -0700 (PDT)

"Edward K. Ream" <edre...@gmail.com> wrote:

> This has no chance of working--the script creates dummy classes which
> are of no value for autocompletion.

I've been trying to build blender from source, because I want to try
enabling an alternate library for 3d object intersection. I think as
part of that process it
creates .../blender-svn/blender/release/scripts/modules/bpy and friends
which might be good targets for codewise. They look like real python.

Haven't had a chance to test yet.

Cheers -Terry

Edward K. Ream

unread,
Sep 13, 2011, 2:40:44 PM9/13/11
to leo-e...@googlegroups.com
On Tue, Sep 13, 2011 at 12:33 PM, Terry Brown <terry_...@yahoo.com> wrote:

> blender-svn/blender/release/scripts/modules/bpy and friends
> which might be good targets for codewise.  They look like real python.

They are, but they are far from the whole story. For example,
bpy.types is missing.

Having said that, it's going to be "interesting" to get inspect to
tell us what we want. An initial attempt has revealed more problems
than solutions, but it is still early days...

Eventually, we are going to have to check what we get against the
docs, especially for bpy.types.x, of which there are very many:
http://www.blender.org/documentation/blender_python_api_2_59_2/bpy.types.html

Edward

Terry Brown

unread,
Sep 13, 2011, 2:50:40 PM9/13/11
to leo-e...@googlegroups.com
On Tue, 13 Sep 2011 13:40:44 -0500

"Edward K. Ream" <edre...@gmail.com> wrote:

> They are, but they are far from the whole story. For example,
> bpy.types is missing.

There is .../blender-svn/blender/release/scripts/modules/bpy_types.py

not sure if it's only created as part of the build process?

Cheers -Terry

Edward K. Ream

unread,
Sep 13, 2011, 4:48:27 PM9/13/11
to leo-e...@googlegroups.com
On Tue, Sep 13, 2011 at 1:50 PM, Terry Brown <terry_...@yahoo.com> wrote:

> There is .../blender-svn/blender/release/scripts/modules/bpy_types.py
>
> not sure if it's only created as part of the build process?

A slightly different path prefix on windows, but I see it. Thanks. I
don't think I got far enough in the build process to generate the
file, so I think it came with the distro.

We are getting close. For sure ;-)

Jaworski's pypredef_gen.py mentions that it is based on Campbell
Barton's sphinx_doc_gen.py, which I gather is enough to generate all
the docs. On my machine, sphinx_doc_gen.py is in the sources distro
at blender/doc/python_api.

The files produced by pypredef_gen.py look like they are plenty good
enough for code completion. There is no .pypredef file for
bpy.context and bpy.types, but might just be because there is no
corresponding entries in the INCLUDE_MODULES list. Of course, these
modules could be special cases that pypredef_gen.py wouldn't be able
to handle, but surely sphinx_doc_gen.py *can* handle the special
cases, so in an emergency we could merge the two scripts.

I'm going to play around with pypredef_gen.py now. An obvious mod
would be to generate .py files (in some safe place) rather than
.pypredef files, and I'll see what happens when it tries to generate
bpy.context and bpy.types...

Edward

Edward K. Ream

unread,
Sep 13, 2011, 6:44:25 PM9/13/11
to leo-editor
On Sep 13, 3:48 pm, "Edward K. Ream" <edream...@gmail.com> wrote:

> I'm going to play around with pypredef_gen.py now.

In hindsight, with the knowledge of Blender gained in the last few
days, it is clear that this program, or something very similar to it,
is just about the only way to get the job done.

Furthermore, there is a lot of Blender-specific information (or hacks)
contained in the script: only an experienced Blender developer would
have any chance of writing it. I was way off in my estimation of the
script: it is a major effort. No way could I reproduce it.

> I'll see what happens when [pypredef_gen.py] tries to generate bpy.context and bpy.types...

bpy2predef appears to handle bpy.context and bpy.data as special cases
by calling::

property2predef("", fw, bpy, "context")
property2predef("", fw, bpy, "data")

bpy_base2predef contains this "comment" put (somewhere) into the
output:

"Note that bpy.types.%s is not actually available from within
blender,
it only exists for the purpose of documentation."

This indicates that bpy.types has not been forgotten, though I can't
say yet what the result is.

I haven't actually run the script yet. It must be run from within
Blender. That's the next step...

Edward

Edward K. Ream

unread,
Sep 13, 2011, 7:47:45 PM9/13/11
to leo-editor
On Sep 13, 5:44 pm, "Edward K. Ream" <edream...@gmail.com> wrote:

> I haven't actually run the [pypredef_gen]script yet.  It must be run from within
> Blender.  That's the next step...

Success! The script just worked. I renamed it py_dgen.py to save
typing, started Blender, and as soon as I imported py_dgen it just
worked.

The only change I have made was a typo: the word "Special" in a common
docstring:

'''Special class, created just to reflect content of
bpy.ops.<whatever>'''

The generated .pypredef files could renamed to be .py files, but that
can be done anytime. There is nothing else that obviously needs to be
done.

In particular, bpy.pypredef is a very large file. It's structure is:

class ops:

class action: # for bpy.ops.action
...
class anim: # for bpy.ops.anim
....
class world: # for bpy.ops.world
....

class types
'''A container for all Blender types'''

class bpy_struct:
'''built-in base class for all classes in bpy.types.

Note that bpy.types.bpy_struct is not actually available from
within blender, it only exists for the purpose of documentation.
'''

[snip]

class Action(types.ID):
...
class ActionActuator(types.Actuator):
....
class XorController(types.Controller):
....

The crucial point is that this file contains all the "synthesized"
classes that don't actually exist as .py files.

And all the other .pypredef files look suitable for autocompletion.

A big step forward.

Edward

P.S. Ha. As I reread the post I see that class types is missing the
colon, as is class bpy_struct. Another typo.

EKR

Edward K. Ream

unread,
Sep 13, 2011, 9:33:34 PM9/13/11
to leo-editor
On Sep 13, 6:47 pm, "Edward K. Ream" <edream...@gmail.com> wrote:

> Success!  The script just worked.

Modifying the script very easy:

1. To rerun the script, just do imp.reload(py_dgen). There is no need
to restart blender, nor is there need for scripts to run scripts.

2. I fixed several bugs in py_dgen:

- In some cases, no docstring at all was being output, which would
cause a syntax error.

- The stubs no longer ever have a return statement. This eliminates
dubious code.
In most cases the docstring indicates the return type.

- Indentation now is 4 spaces, not 3.

The resulting files are likely valid, executable, Python, which was
not the case before.

Edward
Reply all
Reply to author
Forward
0 new messages