Problem Creating a new outline using leoBridge

59 views
Skip to first unread message

SegundoBob

unread,
Jul 26, 2012, 3:05:43 PM7/26/12
to leo-e...@googlegroups.com
I'm trying to create a new Leo-Editor outline file using leoBridge and I'm stuck with this error:

$ python .temp.py
Traceback (most recent call last):
  File ".temp.py", line 17, in <module>
    ptrDay = ptrRoot.insertAsLastChild()
  File "/home/ldi/bzr/LeoLatest/leo/core/leoNodes.py", line 1212, in insertAsLastChild
    n = p.numberOfChildren()
  File "/home/ldi/bzr/LeoLatest/leo/core/leoNodes.py", line 488, in numberOfChildren
    return len(p.v.children)
AttributeError: 'NoneType' object has no attribute 'children'

Here is my program .temp.py:

pathLeo = '/home/ldi/tmp/debug/rfd1207.leo'


import sys

sys.path.append("/home/ldi/bzr/LeoLatest/")

import leo.core.leoBridge as leoBridge


bridge = leoBridge.controller(gui='nullGui',verbose=False)

cmdr = bridge.openLeoFile(pathLeo)

ptrRoot = cmdr.rootPosition()

ptrDay = ptrRoot.insertAsLastChild()

-------- end program ------------------

I seem to have an outline and it seems to have a root position, but this root position does not have a "vnode".

Versions:
Leo Log Window
Leo 4.11 devel, build 5416, 2012-07-01 15:27:23
Python 2.7.2, qt version 4.7.4
linux2  --- This is openSUSE 12.1



Edward K. Ream

unread,
Sep 26, 2013, 1:29:47 PM9/26/13
to leo-editor
On Thu, Jul 26, 2012 at 2:05 PM, SegundoBob <bhos...@ieee.org> wrote:
I'm trying to create a new Leo-Editor outline file using leoBridge and I'm stuck with this error:

​My apologies for the way-too-long delay in responding.

​A program similar to yours works for me. Here are some ideas:

​1. ​sys.path.append(whatever) puts the latest version of Leo at the *end* of sys.path.  Instead, I used sys.path.insert(0,whatever) This should do what you want: ensure that you use the proper Leo.

2. I would insert traces (or use g.pdb(), or pdb.set_trace) to verify each step of your program.

HTH.

Edward

Segundo Bob

unread,
Sep 26, 2013, 3:23:12 PM9/26/13
to leo-e...@googlegroups.com
On 09/26/2013 10:29 AM, Edward K. Ream wrote:
> A program similar to yours works for me. Here are some ideas:

"Similar"? Why don't your run my program or modify it for your system
and run it?

Attached is my revised program. The only changes are to make it clearer
that yes, I am using the latest Leo-Editor code.

Here is the output to the console:

$ python createLeo.py
/home/ldi/bzr/LeoLatest/leo/core/leoBridge.pyc
Leo 4.11a3, build 6062, 2013-09-26 11:10:24
Python 2.7.3, leoGui: dummy version
linux2
file not found: /home/ldi/tmp/newFile.leo. creating new window
Traceback (most recent call last):
File "createLeo.py", line 13, in <module>
ptrDay = ptrRoot.insertAsLastChild()
File "/home/ldi/bzr/LeoLatest/leo/core/leoNodes.py", line 1176, in
insertAsLastChild
n = p.numberOfChildren()
File "/home/ldi/bzr/LeoLatest/leo/core/leoNodes.py", line 489, in
numberOfChildren
return len(p.v.children)
AttributeError: 'NoneType' object has no attribute 'children'
2013-09-26 12:12:49 /home/ldi/tmp
------ End of console output ----------

ptrRoot.v is still None.


--
Segundo Bob
Segun...@gmail.com
createLeo.py

Edward K. Ream

unread,
Sep 26, 2013, 4:36:26 PM9/26/13
to leo-editor
On Thu, Sep 26, 2013 at 2:23 PM, Segundo Bob <segun...@gmail.com> wrote:
On 09/26/2013 10:29 AM, Edward K. Ream wrote:
> A program similar to yours works for me. Here are some ideas:

"Similar"?  Why don't your run my program or modify it for your system
​ ​
and run it?

​That's what I did.​
 

​Edward

Segundo Bob

unread,
Sep 26, 2013, 5:14:57 PM9/26/13
to leo-e...@googlegroups.com
On 09/26/2013 01:36 PM, Edward K. Ream wrote:
> That's what I did.
>

Sorry, I misunderstood you because you did not point out any bugs in my
program yet you implied that it contains bugs. I assumed that if you
had modified my program, you would have noted the bugs you had to fix.

My program is very, very simple:

Using leoBridge:
1) Open a .leo file that does not yet exist.
2) Get the root position for this file.
3) Create a child of the root position.

The problem can actually be seen after step 2 because ptrRoot.v is None
-- on my system.

But on your system, after step 2, ptrRoot.v is a valid vnode?

Do you still think my program contains bugs--even though it works on
your system? Is my open statement incorrect? Is my get root position
incorrect?

Even though bridge.g.app.signon is the expected value, do you still
think that my installation of Leo-Editor is screwed up and I'm using the
wrong leoBridge or wrong some other part of Leo-Editor?

--
Segundo Bob
Segun...@gmail.com

Edward K. Ream

unread,
Sep 26, 2013, 5:53:44 PM9/26/13
to leo-editor
On Thu, Sep 26, 2013 at 4:14 PM, Segundo Bob <segun...@gmail.com> wrote:

My program is very, very simple:

​It's hard to debug remotely.

There is one change, using sys.path.insert(0,path) rather than sys.path.append.

Please verify, say by printing the value of leoBridge, that you are using the correct version of Leo.  Other than that, everything looks as it should.  More, I can't say...

Edward

Segundo Bob

unread,
Sep 26, 2013, 7:04:20 PM9/26/13
to leo-e...@googlegroups.com
On 09/26/2013 02:53 PM, Edward K. Ream wrote:
> It's hard to debug remotely.
>
> There is one change, using sys.path.insert(0,path) rather than
> sys.path.append.
>
> Please verify, say by printing the value of leoBridge, that you are
> using the correct version of Leo. Other than that, everything looks as
> it should. More, I can't say...

Yes, it is hard to debug remotely. Particularly when you don't look at
what I send you.

I dropped the use of sys.path.append(). It was never necessary in my
environment. I had put it in to make the program easier to adapt for
people who do not have the root of their Leo-Editor installation in
their PYTHNPATH.

Printing the value of leoBridge doesn't tell me anything about its version:

<module 'leo.core.leoBridge' from
'/home/ldi/bzr/LeoLatest/leo/core/leoBridge.pyc'>

That is why in my post at 12:23 today I sent you code containing:

print(bridge.g.app.signon)
print(bridge.g.app.signon2)

And the output of these two print statements:

Leo 4.11a3, build 6062, 2013-09-26 11:10:24
Python 2.7.3, leoGui: dummy version
-----------

Perhaps you can post your simple program that works and I and others can
try it on our systems.

--
Segundo Bob
Segun...@gmail.com

Terry Brown

unread,
Sep 26, 2013, 8:47:42 PM9/26/13
to leo-e...@googlegroups.com
On Thu, 26 Sep 2013 14:14:57 -0700
Segundo Bob <segun...@gmail.com> wrote:

> On 09/26/2013 01:36 PM, Edward K. Ream wrote:
> > That's what I did.
> >
>
> Sorry, I misunderstood you because you did not point out any bugs in my
> program yet you implied that it contains bugs. I assumed that if you
> had modified my program, you would have noted the bugs you had to fix.
>
> My program is very, very simple:
>
> Using leoBridge:
> 1) Open a .leo file that does not yet exist.

So, is opening an non-existent file actually the right way to create a
file de novo from leoBridge? It fails for me as Segundo Bob reports.

I also tried

g = bridge.globals()
c = g.app.newCommander(None)

but that fails the same way, i.e.

p = c.rootPosition()
c.positionExists(p)
Out[19]: False

So perhaps the question should be "how do you create an empty outline
from leoBridge", not "why doesn't this code work".

This works:

import sys
sys.path.insert(0, './leo')
import leo.core.leoBridge as leoBridge
bridge = leoBridge.controller(gui='nullGui', verbose=False,
loadPlugins = False,readSettings = False)
g = bridge.globals()
c = bridge.createFrame('/tmp/test22_del.leo')
p = c.rootPosition()
c.positionExists(p) # False
c.frame.createFirstTreeNode()
p = c.rootPosition()
c.positionExists(p) # True
nd = p.insertBefore()
nd.h = "Before..."
c.save()

took some source reading to get there though.

Cheers -Terry

Segundo Bob

unread,
Sep 27, 2013, 10:22:47 AM9/27/13
to leo-e...@googlegroups.com
Terry Brown:

Many thanks Terry. The call to cmdr.frame.createFirstTreeNode() seems
to be the crucial operation required when creating a new Leo-Editor file
with leoBridge.

This works for me:

bridge = leoBridge.controller(gui='nullGui', verbose=False,
loadPlugins = False,readSettings = False)
cmdr = bridge.openLeoFile('/home/ldi/tmp/newFile.leo')
cmdr.frame.createFirstTreeNode()
ptrRoot = cmdr.rootPosition()
ptrDay = ptrRoot.insertAsLastChild()

Many thanks.

--
Segundo Bob
Segun...@gmail.com

Edward K. Ream

unread,
Sep 27, 2013, 2:25:54 PM9/27/13
to leo-e...@googlegroups.com


On Friday, September 27, 2013 9:22:47 AM UTC-5, SegundoBob wrote:

> The call to cmdr.frame.createFirstTreeNode() seems to be the crucial operation required when creating a new Leo-Editor file with leoBridge.

That's a bug, imo.  bridge.openLeoFile should call c.frame.createFirstTreeNode automatically.  createFirstTreeNode is an internal helper, not intended for outside use.

This bug has been fixed at rev 6072. Here is the checkin log:

Fixed bug in leoBridge: bridgeController.createFrame now calls frame.createFirstTreeNode for new frames.

And here is a test that demonstrates the new code::

    import sys
    sys.path.insert(0,'c:/leo.repo/trunk/leo')
    import leo.core.leoBridge as leoBridge
    print(leoBridge)
    cc = leoBridge.controller(gui='nullGui',verbose=False)
    path = 'c:/Users/edreamleo/does-not-exist.leo'
    c = cc.openLeoFile(path)
    root = c.rootPosition()
    assert root
    root.h = 'root'
    p = root.insertAsLastChild()
    'A'
    assert p
    for p in c.all_positions():
        print(p.h)

Edward

Terry Brown

unread,
Sep 27, 2013, 2:38:25 PM9/27/13
to leo-e...@googlegroups.com
On Fri, 27 Sep 2013 11:25:54 -0700 (PDT)
"Edward K. Ream" <edre...@gmail.com> wrote:

>
>
> On Friday, September 27, 2013 9:22:47 AM UTC-5, SegundoBob wrote:
>
> > The call to cmdr.frame.createFirstTreeNode() seems to be the crucial
> operation required when creating a new Leo-Editor file with leoBridge.
>
> That's a bug, imo. bridge.openLeoFile should call
> c.frame.createFirstTreeNode automatically. createFirstTreeNode is an
> internal helper, not intended for outside use.
>
> This bug has been fixed at rev 6072. Here is the checkin log:

Just pulled and tested your code below. All ok except c.saveAs()
doesn't really seem to work as expected. Maybe I'm not using it right.

Cheers -Terry

Edward K. Ream

unread,
Sep 28, 2013, 7:33:49 AM9/28/13
to leo-editor
On Fri, Sep 27, 2013 at 1:38 PM, Terry Brown <terry_...@yahoo.com> wrote:

Just pulled and tested your code below.  All ok except c.saveAs()
doesn't really seem to work as expected.  Maybe I'm not using it right.

​Thanks for doing this testing.  There are several problems with c.saveAs(), and presumably c.save and c.saveTo. I'll fix them next.

Edward

Edward K. Ream

unread,
Sep 28, 2013, 8:09:26 AM9/28/13
to leo-editor
On Sat, Sep 28, 2013 at 6:33 AM, Edward K. Ream <edre...@gmail.com> wrote:

​> ​
​Thanks for doing this testing.  There are several problems with c.saveAs(), and presumably c.save and c.saveTo. I'll fix them next.

​Done at rev 6074.  To emphasize what is said below in the checkin log, there is a systemic problem with the leoBridge module: it uses a nullGui in which all dialogs are do-nothings.  This will affect all commands, such as c.save, etc., that may (or may not) ask the user for input.

The workaround I used for c.save, c.saveAs and c.saveTo was to add a "fileName" keyword arg, so that code using a commander returned by leoBridge can just demand that a certain fileName be used. This is as far as I am willing to go for the 4.11 release.

Here is the checkin log:

QQQ​
    Added fileName keyword arg and associated logic to c.save, c.saveTo and c.saveAs.
   
    These tweaks are only the tip of an iceberg: the nullGui doesn't have [any] way
    of returning values from its dummy dialogs.
   
    The following test, call it leo-bridge-test.py, passes::
   
    # Do *not* execute this from inside Leo!
    if __name__ == '__main__':
        import os

        import sys
        sys.path.insert(0,'c:/leo.repo/trunk/leo')
        import leo.core.leoBridge as leoBridge
        print(leoBridge)
        cc = leoBridge.controller(gui='nullGui',verbose=False)
        g = cc.globals()
        path = 'c:/Users/edreamleo/does-not-exist.leo'
        assert not os.path.exists(path),path
        assert not g.os_path_exists(path),path

        c = cc.openLeoFile(path)
        root = c.rootPosition()
        assert root
        root.h = 'root'
        p = root.insertAsLastChild()
        p.h = 'A'
        assert p and p.h
        if 0:

            for p in c.all_positions():
                print(p.h)
        path = 'c:/Test/leo-bridge-test.leo'
        c.save(fileName=path)
        assert os.path.exists(path),path
        assert g.os_path_exists(path),path
        os.remove(path)
        assert not os.path.exists(path),path
        assert not g.os_path_exists(path),path
        c.saveAs(fileName=path)
        assert os.path.exists(path),path
        assert g.os_path_exists(path),path
        c.saveTo(fileName=path)
        assert os.path.exists(path),path
        assert g.os_path_exists(path),path
QQQ

Edward

Terry Brown

unread,
Sep 28, 2013, 10:37:59 AM9/28/13
to leo-e...@googlegroups.com
On Sat, 28 Sep 2013 07:09:26 -0500
"Edward K. Ream" <edre...@gmail.com> wrote:

> Done at rev 6074. To emphasize what is said below in the checkin log,
> there is a systemic problem with the leoBridge module: it uses a nullGui in
> which all dialogs are do-nothings. This will affect all commands, such as
> c.save, etc., that may (or may not) ask the user for input.

Ah, makes sense now you point it out - tricky. Explicit filename's ok
for saveAs, a more general solution is hard to imagine. If all dialogs
flowed through a single execution pathway / wrapper, you might be able
to use something like:

c.pushDialogResult(someResult)
c.functionUsingADialog() # null gui returns someResult

- maybe a common execution pathway / wrapper for dialogs isn't
critical, this could be part of the implementation of the nullGui
dialogs.

- how many cases are we really talking about? I can't think of any
others beyond saveAs. I guess there's a bunch of save<somethings>

Cheers -Terry

Edward K. Ream

unread,
Sep 28, 2013, 2:00:17 PM9/28/13
to leo-editor
On Sat, Sep 28, 2013 at 9:37 AM, Terry Brown <terry_...@yahoo.com> wrote:
On Sat, 28 Sep 2013 07:09:26 -0500

​> ​
Ah, makes sense now you point it out - tricky.  Explicit filename's ok
​ ​
for saveAs, a more general solution is hard to imagine.

​I agree. Even if a more general solution existed, explicit is usually preferable to implicit--explicit file names given to functions and methods are the simplest thing that could possibly work in a scripting environment such as leoBridge.


> how many cases are we really talking about?

​Heh.  Roughly the commands for which ​the menu should have ... :-)  That is, all commands that bring up a user dialog.  Read/Write commands, import/export commands, compare-leo-file, that sort of thing.

All this is a pretty low priority now.  I wonder how many people actually use the leoBridge?

EKR

Edward K. Ream

unread,
Sep 28, 2013, 2:12:01 PM9/28/13
to leo-e...@googlegroups.com
On Saturday, September 28, 2013 1:00:17 PM UTC-5, Edward K. Ream wrote:

> explicit file names given to functions and methods are the simplest thing that could possibly work in a scripting environment such as leoBridge.
...

All this is a pretty low priority now...

A fundamental reason why there is little urgent need for scripting support in leoBridge is that scripts can always "borrow" code from Leo's core.  For instance, when fileName is known, c.saveTo is equivalent (ignoring gui issues that don't apply in leoBridge), to::

    fileName = g.ensure_extension(fileName, ".leo")
    c.fileCommands.saveTo(fileName)
    g.app.recentFilesManager.updateRecentFiles(fileName)
    g.chdir(fileName)

So, although official support for file-related operations in leoBridge would be nice, scripts that use leoBridge can always supply their own equivalent code.

EKR

Kent Tenney

unread,
Sep 28, 2013, 3:11:36 PM9/28/13
to leo-editor
> I wonder how many people actually use the leoBridge?

+1 here

Most of the Leo-related code I mull is based on leoBridge: given
my interest in Leo as a data store with great editing capabilities:
manipulating Leo files programatically is crucial for my interests.

Thanks,
Kent
> --
> You received this message because you are subscribed to the Google Groups
> "leo-editor" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to leo-editor+...@googlegroups.com.
> To post to this group, send email to leo-e...@googlegroups.com.
> Visit this group at http://groups.google.com/group/leo-editor.
> For more options, visit https://groups.google.com/groups/opt_out.

Edward K. Ream

unread,
Sep 28, 2013, 3:15:47 PM9/28/13
to leo-editor
On Sat, Sep 28, 2013 at 2:11 PM, Kent Tenney <kte...@gmail.com> wrote:
> I wonder how many people actually use the leoBridge?

+1 here

​Thanks.  One might think, judging from the recent discussions, that leoBridge is broken.  Good to know that it is not!

Edward

Kent Tenney

unread,
Sep 28, 2013, 3:47:06 PM9/28/13
to leo-editor
Right, I use a subset of capability which hasn't given problems.
It's great to see others provoking bugs which are being fixed!

Terry Brown

unread,
Sep 28, 2013, 4:02:38 PM9/28/13
to leo-e...@googlegroups.com
On Sat, 28 Sep 2013 13:00:17 -0500
"Edward K. Ream" <edre...@gmail.com> wrote:

> All this is a pretty low priority now. I wonder how many people actually
> use the leoBridge?

I think it's an important part of the suite. For example, can't
remember the details, but my script for updating the global search db
uses it - that kind of thing is a significant source of capability.

Cheers -Terry
Reply all
Reply to author
Forward
0 new messages