In the Contributing to Flexx 
<https://flexx.readthedocs.io/en/stable/contributing.html> page Almar says, 
"it’s very useful to hear what you like and what you struggle with. This 
post summarizes both topics.

*===== Part 1: What I like about flexx*

Flexx makes bi-directional, asynchronous communication between Python and 
the browser as simple as it could possibly be. Specifically: 

*1. Simple code suffices*. The top-level flexx code to draw Leo's main 
window could be as simple as:

class LeoMainWindow(flx.Widget):

    def init(self, body, outline):
        with flx.VBox():
            with flx.HBox(flex=1):
                LeoTree(outline, flex=1)
                LeoLog(flex=1)
            LeoBody(body, flex=1)
            LeoMiniBuffer()
            LeoStatusLine()

As discussed later, we might want to add flexx properties to this code to 
make the individual components more easily accessible to other classes.

*Important*: As shown above, init methods can take extra *non*-keyword args 
(body and outline) which can then be passed to "inner" flx.Widgets.  In 
turn flexx (magically) passes those args to the init methods of the inner 
Widgets.  Nothing special needs to be done to make this happen! This 
greatly simplifies communication between components. There is typically no 
need to define __init__ methods.


*2. Pscript rocks*

The pscript documentation 
<https://pscript.readthedocs.io/en/latest/intro.html#pscript-is-just-javascript>
 
says: "[Unlike] Skulpt or PyJS...PScript takes a more modest approach; it 
is a tool that allows one to write JavaScript with a Python syntax. PScript 
is just JavaScript."

This limited goal shows superb engineering judgment. Its simplicity makes a 
huge difference.  The pscript compiler is straightforward!

One need not worry greatly about the differences between pscript and 
python, for several reasons:

- Error reporting is excellent. The one time I used a Python construct (a 
generator inside a list) that pscript does not support at present, pscript 
gave me a clear error message.

- Typical flexx programs will be as simple as the example shown above.  
Pscript undoubtedly suffices to handle such code.  Imo, that's all that 
matter. 

3. *The documentation and support are excellent*

Flexx's docs are easy to read and comprehensive.  By almost any measure 
they are superior to Leo's. The examples, demos and how-to's are especially 
valuable.

I have asked Almar two questions on flexx's issue tracker 
<https://github.com/flexxui/flexx/issues?q=is%3Aissue+is%3Aopen>. Each time 
I received a prompt, helpful, and courteous reply.

*===== Part 2: What I struggled with*

I have just said that flexx's docs are excellent.  Nevertheless, it has 
taken four days of intense work for me to attain limited proficiency.  This 
is completely expected.  I learn by doing, not by reading.

After yesterday's work I am much more confident that I can use flexx as 
Almar himself might use it. Now is the time to write this section, while 
the difficulties and confusions are still fresh in my mind.

*What gets compiled to pscript?*

This has been a big confusion.  *Just now* I see that Almar answered this 
question completely here 
<https://github.com/flexxui/flexx/issues/513#issuecomment-436239072>.  So 
the answer is: PyComponents are *not* JS. That helps a lot.

For example, LeoApp is a flx.PyComponent, so its open_bridge, find_body and 
get_outline_list methods do *not* get compiled to JS.  If they did, they 
could not possibly work, because these methods use Leo's Commander objects 
(c), and there is no way that JS is ever going to be able to deal with this 
class.  Indeed, a few days ago I was getting JS errors to that effect.

In this reply 
<https://github.com/flexxui/flexx/issues/513#issuecomment-436241088>, Almar 
said: "this pinpoints Flexx' weak spot; it makes writing Js classes so 
familiar that confusion arises :/ I'd recommend to separate the two as good 
as you can. Be explicit in comments / docstrings. Probably don't mix the 
two in a single module."

Well, this is a pretty small weak spot :-) Devs obviously must distinguish 
carefully between the Python and JS sides!  That's a big part of what 
coming up to speed with flexx entails.

At present leoflexx.py contains two top-level organizer nodes called:

- Py side: flx.PyComponents
- Js side: flx.Widgets

Imo, these "comments" suffice.  It would not be Leonine to put those two 
sub-outlines in separate modules.

*When does transpiling happen?*

Traces reveal that pscript issues errors as the server starts up.  Again, 
this could be called a Doh! moment.  Where else is the transpiling going to 
happen?  Still was helpful to get that leoflexx.py is *just* a python 
program as far as python itself is concerned.  The magic happens later.

*How to communicate between components?*

Given the example above, you would think this would be no big deal, but it 
was a very big deal indeed. The example is the result of many hours of 
work.  Yes, it looks like many of the flexx examples, but that didn't help 
me at the time.

If I have one small suggestion to make, it might be an earlier discussion 
of this topic.  But maybe not. After all there is a discussion of the root 
component 
<https://flexx.readthedocs.io/en/stable/guide/widgets_components.html#the-root-component>.
 
I didn't pay much attention to this as I skimmed through the docs the first 
few times.

Perhaps a separate section about init methods would be helpful.  It wasn't 
clear to me until I tried it that the example code above would "just 
work".  That is, it wasn't clear that calling a *ctor* with an "extra" 
non-keyword arg would automagically add that arg to the init method in the 
called class!

Anyway, communication between the python and JS sides is obviously 
crucial.  No way does it ever just happen.  That's much clearer to me now.

My initial code used global vars for communication.  In retrospect, that's 
a laughable idea, but I was clueless.  The road forward started with a 
jolt:  Aha: Python's/pscript's "global" statement does not mean the same 
thing on the Python and JS sides!  Doh!

Actually, I'm not sure how to state this Aha with any kind of rigor.  
Clearly, the Python and JS sides must eventually communicate via sockets, 
and it would be expecting way too much for "global" to create a socket or 
proxy.

Happily, flexx properties provide everything needed.  Apparently, 
properties must be used to communicate even between different flx.Widgets.  
That is, the ivars of one widget are not accessible to other flx.Widgets.  
So the example code above might better be rewritten this way:

class LeoMainWindow(flx.Widget):
    
    """
    Leo's main window, that is, root.main_window.
    
    Each property x below is accessible as root.main_window.x.
    """
    
    body = flx.AnyProp(settable=True)
    log = flx.AnyProp(settable=True)
    minibuffer = flx.AnyProp(settable=True)
    status_line = flx.AnyProp(settable=True)
    tree = flx.AnyProp(settable=True)

    def init(self, body, outline):
        with flx.VBox():
            with flx.HBox(flex=1):
                tree = LeoTree(outline, flex=1)
                log = LeoLog(flex=1)
            body = LeoBody(body, flex=1)
            minibuffer = LeoMiniBuffer()
            status_line = LeoStatusLine()
        self._mutate_body(body)
        self._mutate_log(log)
        self._mutate_minibuffer(minibuffer)
        self._mutate_status_line(status_line)
        self._mutate_tree(tree)

Almar, please correct me if I am wrong about this.

*Summary*

This post has discussed what I like about flexx and what confused me while 
I was coming up to speed.

Flexx and pscript are pure genius. They solve important practical problems 
more elegantly than I would have thought possible.

Learning how to use flexx hasn't been easy, but then I hardly expected that 
it would <https://www.youtube.com/watch?v=ndL7y0MIRE4>, especially as I was 
a complete newbie to web apps when I started.

As always, questions and comments are welcome.

Edward

-- 
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+unsubscr...@googlegroups.com.
To post to this group, send email to leo-editor@googlegroups.com.
Visit this group at https://groups.google.com/group/leo-editor.
For more options, visit https://groups.google.com/d/optout.

Reply via email to