Coder Social home page Coder Social logo

flexxui / flexx Goto Github PK

View Code? Open in Web Editor NEW
3.2K 138.0 259.0 4.45 MB

Write desktop and web apps in pure Python

Home Page: http://flexx.readthedocs.io

License: BSD 2-Clause "Simplified" License

Python 97.47% JavaScript 2.52% CSS 0.01%
python ui web html5

flexx's Introduction

Flexx

CI Documentation Status PyPI version

Want to stay up-to-date about (changes to) Flexx? Subscribe to the NEWS issue.

Introduction

Flexx is a pure Python toolkit for creating graphical user interfaces (GUI's), that uses web technology for its rendering. Apps are written purely in Python; The PScript transpiler generates the necessary JavaScript on the fly.

You can use Flexx to create (cross platform) desktop applications, web applications, and export an app to a standalone HTML document. It also works in the Jupyter notebook.

The docs are on Readthedocs. the code is on Github.

Example

Click the image below for an interactive example:

demo

Motivation

The primary motivation for Flexx is the undeniable fact that the web (i.e. browser technology) has become an increasingly popular method for delivering applications to users, also for (interactive) scientific content.

The purpose of Flexx is to provide a single application framework to create desktop applications, web apps, and (hopefully someday) mobile apps. By making use of browser technology, the library itself can be relatively small and pure Python, making it widely available and easy to use.

A word of caution

Flexx is very versatile and can be used in different ways. It also makes it easy to mix Python that runs on the server and Python that runs in the browser. This is a powerful feature but this also makes it easy to create code that becomes difficult to maintain. You, the developer, must ensure that Python and PScript code are clearly separated.

Installation

Flexx requires Python 3.5+ and also works on pypy. Further, it depends on:

  • the Tornado library (pure Python).
  • the PScript library (a pure Python flexxui project).
  • the Webruntime library (a pure Python flexxui project).
  • the Dialite library (a pure Python flexxui project).

To install the latest release (and dependencies), use either of:

# Install latest release
pip install flexx

# Install latest from Github
pip install -U https://github.com/flexxui/flexx/archive/master.zip

Or get the bleeding edge with:

  • pip install https://github.com/flexxui/flexx/archive/master.zip

Supported browsers

Flexx aims to support all modern browsers, including Firefox, Chrome and Edge. Internet Explorer version 10 and up should work, but some things may be flaky.

For running desktop apps, it is needed to have Firefox or NW.js installed.

License

Flexx makes use of the liberal 2-clause BSD license. See LICENSE for details.

flexx's People

Contributors

a03ki avatar aars avatar alexveden avatar almarklein avatar btwe avatar ceprio avatar dwillmer avatar gitter-badger avatar gregfreeman avatar grimmaldi avatar hittingsmoke avatar ibell avatar ikaradogan avatar ivoflipse avatar jrversteegh avatar kamoser avatar kevinlondon avatar konubinix avatar matkuki avatar maxyme avatar ocobacho avatar pierrejean-coudert avatar pigay avatar scotthuangzl avatar scottwedge avatar sesh avatar stonebig avatar tbnorth avatar timgates42 avatar toddrme2178 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

flexx's Issues

No flexx/ui/_iframe.py

The example hello_world.py fails:

Traceback (most recent call last):
  File "hello_world.py", line 6, in <module>
    from flexx import app, ui
  File "/Users/mike/Dev/flexx/flexx/ui/__init__.py", line 90, in <module>
    from ._iframe import IFrame
Traceback (most recent call last):
  File "hello_world.py", line 6, in <module>
    from flexx import app, ui
  File "/Users/mike/Dev/flexx/flexx/ui/__init__.py", line 90, in <module>
    from ._iframe import IFrame

Looks like lexx/ui/_iframe.py has not been checked in yet. Commenting out the line from ._iframe import IFrame fixes the problem.

Event system

We need an event system and I think it makes sense to make it symmetric as we do with properties: the PyScript API is the same as the Python API.

In any case, we need a way for methods to be event handlers, and have the correct this. We can do this with an API like:

xxx(..., my_function)
xxx(..., (my_object, 'my_method'))

Option A: name based like JS

button.connect_event('click', my_handler)
button.disconnect_event('click', my_handler)
button.emit_event('click', event)

@button.connect_event('click')
def my_handler(event):
    ...

Cannot use autocompletion, so ppl need to read the docs to know what events are available. But I think its Pythonic. It also feels simple and compact.

Option B: full names similar to Vispy

button.events.click.connect(my_handler)
button.events.click.disconnect(my_handler)
button.events.click(event)   # vispy-style-emitting, but we cannot do this in JS
button.events.click.emit(event)  # explicit

@button.events.click.connect
 def my_handler(event):
    ...

A bit verbose, but autocomp is nice to have.

Option C: No events; use reactive programming

See #15

other ideas? ....

The event object

Also, the event object, we can start with following the JS API. Although we cannot really use native events, because these are for DOM objects. Maybe for clarity also use "owner" instead of "target", etc.

error `object does not have a signal` trying `find_prime.py`

on today trunk, trying find_prime.py gives this to me:

Traceback (most recent call last):
  File "D:/WinPythonQt5/basedir34/build/winpython-3.4.3.amd64/notebooks/find_prime.py", line 60, in <module>
    finder = app.launch(PrimeFinder, 'nodejs')  # can also use Firefox or Chrome
  File "D:\WinPythonQt5\basedir34\build\winpython-3.4.3.amd64\python-3.4.3.amd64\lib\site-packages\flexx\app\funcs.py", line 185, in launch
    session = manager.create_session(cls.__name__)
  File "D:\WinPythonQt5\basedir34\build\winpython-3.4.3.amd64\python-3.4.3.amd64\lib\site-packages\flexx\app\session.py", line 85, in create_session
    app = cls(session=session, container='body')
  File "D:\WinPythonQt5\basedir34\build\winpython-3.4.3.amd64\python-3.4.3.amd64\lib\site-packages\flexx\app\model.py", line 244, in __init__
    react.HasSignals.__init__(self, **kwargs)
  File "D:\WinPythonQt5\basedir34\build\winpython-3.4.3.amd64\python-3.4.3.amd64\lib\site-packages\flexx\react\hassignals.py", line 87, in __init__
    raise ValueError('Object does not have a signal %r' % name)
ValueError: Object does not have a signal 'container'
>>> 

Example on Flexx's github page fails

I tried to run the example code that appears on Fluxx's Github page. I put the code that appears there into the file test1.py:

(py34)Gary-Robinsons-Retina-Macbook-Pro:flexx garyrob$ python test1.py
Serving apps at http://localhost:49270/
Traceback (most recent call last):
File "test1.py", line 17, in <module>
    main = app.launch(Example)
File "/Users/garyrob/anaconda/envs/py34/lib/python3.4/site-packages/flexx/app/proxy.py", line 387, in launch
    proxy = Proxy(cls.__name__, runtime, **runtime_kwargs)
File "/Users/garyrob/anaconda/envs/py34/lib/python3.4/site-packages/flexx/app/proxy.py", line 451, in __init__
    self._launch_runtime(runtime, **runtime_kwargs)
File "/Users/garyrob/anaconda/envs/py34/lib/python3.4/site-packages/flexx/app/proxy.py", line 500, in _launch_runtime
    runtime=runtime, **runtime_kwargs)
File "/Users/garyrob/anaconda/envs/py34/lib/python3.4/site-packages/flexx/app/proxy.py", line 384, in launch
    return webruntime.launch(cls, runtime, **runtime_kwargs)
File "/Users/garyrob/anaconda/envs/py34/lib/python3.4/site-packages/flexx/webruntime/__init__.py", line 111, in launch
    rt = Runtime(**kwargs)
File "/Users/garyrob/anaconda/envs/py34/lib/python3.4/site-packages/flexx/webruntime/common.py", line 91, in __init__
    BaseRuntime.__init__(self, **kwargs)
File "/Users/garyrob/anaconda/envs/py34/lib/python3.4/site-packages/flexx/webruntime/common.py", line 30, in __init__
    self._launch()
File "/Users/garyrob/anaconda/envs/py34/lib/python3.4/site-packages/flexx/webruntime/xul.py", line 274, in _launch
    exe = self._get_app_exe(xul_exe, app_path)
File "/Users/garyrob/anaconda/envs/py34/lib/python3.4/site-packages/flexx/webruntime/xul.py", line 455, in _get_app_exe
    self._osx_create_app(op.realpath(xul_exe), exe, title)
File "/Users/garyrob/anaconda/envs/py34/lib/python3.4/site-packages/flexx/webruntime/xul.py", line 519, in _osx_create_app
    icon = Icon(self._kwargs['icon'])  # accepts ico/png/bmp
File "/Users/garyrob/anaconda/envs/py34/lib/python3.4/site-packages/flexx/util/icon.py", line 269, in __init__
    self.read(filename)
File "/Users/garyrob/anaconda/envs/py34/lib/python3.4/site-packages/flexx/util/icon.py", line 294, in read
    raise ValueError('Icon.read() needs a file name')
ValueError: Icon.read() needs a file name

Test visual output - grab browser screenshot (also on CI)

We should have tests to validate visual output of widgets and apps. These should be runnable both locally and on Travis. We'd want to be able to run the tests for each browser that we support. On CI it might be ok to do only FF, but would be nice to do all.

General options:

  • Selenium webdriver is sort of what flexx.webruntime does, but with more control. First time I tried it did not catch FF. Needs exes to be on PATH. Easy support for grabbing screenshots. For chrome it needs a chromedriver.
  • PhantomJS is a webkit-based headless browser.
  • I can make a webkit browser with high control via PyQt.
  • On Linux (and maybe also OSX) I can grab a screenshot from any process that I have the pid of using imagemagix. This could be a good quick way to allow testing on browsers locally.
  • On Windows I can do the same (via ctypes).

CI options:

  • Travis comes with FF installed and xvfb.
  • Appveyor probably has IE.
  • Chrome?
  • Saucelabs is a service where you can test all OS/browser combos (also mobile). Free for OSS. Can be linked to Travis CI. (pip install from repo to get py3k compat). Uses Selenium to remotely run the VM (run from Travis).
  • There is also browserstack.com (free for OSS)
  • applitools allows visual testing (semi-automated)

Eventually we'd want to test for several browsers in CI using saucelabs. For the short term, we should aim for a solution that can be run locally and also on Travis.

Approach:

  • In the main repo we have a directory with .py files that each describe a static app
  • These apps are exported to HTML and published via a git repo. The commit is tagged to make it corresponding to the commit of the main repo.
  • We run browser tests on these apps, and compare the results with images in yet another repo. If not on Travis, the system will prompt the user if a new app is present or if a comparison fails. The user can then mark the result as good or bad. Once a good image is present for each app, the images-repo is committed, and tagged with the same commit-id.

Chrome has problems with nested BoxLayout

Saw this in a Boxlayout in a Boxlayout with a Widget in between. And also with nexted vboxes with an hbox in between.

from flexx import app, ui

class TestApp2(ui.Widget):

    def init(self):

        with ui.VBox(flex=1):

            ui.Widget(style='background:#f00; min-height:100px;')
            TestSubApp2(flex=1)
            ui.Widget(style='background:#f00; min-height:100px;')


class TestSubApp2(ui.Widget):

    def init(self):
        with ui.VBox(flex=1):

            ui.Widget(flex=1, style='background:#0f0; min-height:100px;')
            ui.Widget(flex=2, style='background:#00f; min-height:100px;')


m = app.launch(TestApp2, 'chrome')

The VBox inside the sub-app does not take up all available space for some reason. Also not if its an hbox.

Configuration

We need a simple way to configurarion some aspects of Flexx. A unified approach so that each config option can be set:

  • from Python
  • via command line args
  • via environment vars
  • via a config file

New event system

This issue describes a new event system to replace flexx.react. Discussions welcome.

The event system for Flexx should, like the rest of Flexx, be simple and intuitive to use. The current system borrowed some ideas from reactive programming to achieve this. I was initially enthousiastic about RP, but in retrospect I don't think its the right model.

The current system

The system in flexx.react was a fun experiment, and it certainly has some nice features, but it also has some flaws:

  • This "reactive programming" model does not work well in all UI situations, in particular applications geared towards visualization. The reason is that some things are events, and sometimes you need more information than just a single value.
  • The fact that object "properties" are set/get with a function call is not very Pythonic. Even though I've gotten used to the idea, I still commonly make the mistake of using assignment. This is also a hurdle for newcomers.
  • Scroll events don't let themselves be mapped to signals trivially; because scroll events are always relative.
  • Unnecessary events to initialize signal values (i.e. the mouse_down state to False)

The good features can be summarized as:

  • Being able to connect to an event using a decorator at the function that is going to handle the event.
  • Being able to easily connect to multiple events.
  • Dynamism (e.g. connect to 'children.*.size').
  • An anologue and API compatible implementation in JS.

The new system

I am planning/proposing a new event system that is somewhat more conventional, in that it uses events, but has the nice features of the current system.

What this new system will have (that the current system has not):

  • A better name, as react leans towards RP and is confusing with reactjs.
  • Events are handled in the next event loop iteration (unless there is no event loop, in which case events are probably handled synchronously).
  • Event handlers can also be called manually (i.e. an event handler remains a callable).

Generating events

Events can only apply to HasEvents objects (you cannot create events on their own, as you could with signals). You can emit an event using x.emit(name, **values). This causes an event object to be created, which is basically a dictionary from values with some extra info, like owner.

Edit: I think it makes sense to allow emitting events doing x.event_name(ob), which will use ob to produce and emit an event object.

Event objects

Event objects are simply dicts with some fields. For property-change-events, the fields will be 'value', 'previous_value', 'time', 'previous_time', 'owner'. I think it would be useful to create a subclass to allow easier accessing using ev.value, but otherwise they're just dicts.

Connecting to events

You can connect to an event using:

@connect('foo')
def on_foo(*events):
    ...

@connect('foo', 'bar')
def update(*events):
    ...

The decorator is basically the same as it is now, but the function signature now accepts a series of events objects. Even for on_foo(), the function can be called with multiple 'foo' events, if multiple events where generated during one event loop iteration. Event handlers are free to process all events or only the last one (as update() will likely do). The decorator turns the function into a callable object (maybe even the original function?), so that you can manually call update(), which causes events to be empty.

Properties

A decorator @prop replaces the @input and can be used to create properties. When a property is changed, an event with the same name is emitted, which contains information about the new value, old value, and timings.

Similarly, there will be a @readprop (or different name?) decorator for readonly properties (much like the current @source.

class Foo(HasEvents):
    @prop
    def name(s='John'):
        return str(s).capitalize()

foo = Foo()

@connect('foo.name')
def on_name_change(*events):
    print('name %r changed to %r' % (events[-1].value, events[0].previous_value)

foo.name = 'X'
foo.name = 'jane'

# in the next event loop, we will see one message saying "name 'John' changed to 'Jane'".

Defining events

Event can be defined using

class Foo(HasEvents):

    # Short
    my_event = Event('x', 'y',  # x and y are names that the event object will have
                                  docs='docs on this event')

   # I also like this, its 2 lines more, but it allows more flexibility, it allows
   # emitting events using `foo.my_event(ob)`, and I prefer writing docstrings this way.  
   @event
    def my_event(ob):
        """ docs on this event """
        return Event(x=ob.x, y=ob.y)   # create Event object based on input passed to `emit()`.

Streams and caching

One central concept of RP is that you have streams of signals, where new signals are created from a combination of signals etc. A model like this is still possible, by emitting new events from inside an event handler. We can consider using yield to generate new events.

Another concept of RP is caching of signal values, which can help make apps that have a long-running operation to run efficiently. I think that it will take little extra effor to create a proxy event to implement this in the new system.

Event handling order and propagation

Because multiple events can be handled by a single function, handlers are not called in the order in which they were connected. The order should be deterministic, and I think it makes sense to use the event handler name for this. Event order can be influenced by chosing the handler name, and by a keyword argument to the decorator, e.g. @connect('foo', 'bar', key='__need this first'). A handler can not prevent the event being passed to other handlers.

The system itself does not implement any form of event propagation, though systems using it can do so. Here's an (overly simplified) example:

class RootNode(Node):
     @connect('somewhere.mouse_down')
     def _on_mouse_event(self, ev): 
         ev.handled = False
         for node in reversed(children):
               node.mouse_event(ev)
               if ev.handled:
                    break

class NodeThatReactsToLMB(Node):
     def mouse_event(self, ev): 
         if ev.button == 1:
             ...
             ev.handled = True

class NodeThatReactsToRMB(Node):
     def mouse_event(self, ev): 
         if ev.button == 2:
             ...
             ev.handled = True

Loose ends

Suggestions and discussion welcome!

  • A name for this subpackage. Perhaps something derived of "zanshin"? Or something general enough to represent the ideas of property and event.
  • Does each event need a placeholder, or can events exist by virtue of just emitting them?
  • Name for readonly property.

Reactive Programming?

Wrote summary and ideas down here: https://github.com/zoofIO/flexx/wiki/Functional-Reactive-Programming

This issue should be more about API design and implementation.

JS compat

Whatever API we come up with, we must be able to apply it to PyScript and have it work in JS too.

Combining with "property" system

Input signals are quite similar to properties/traits. However, if we want to allow access to the signal object, we cannot do:

 > foo.title = 'new title'
 > foo.title
 new title   # -> should be <signal instance at 0x123>

Solutions:

  • A: signal objects cannot be accessed directly, only indirectly by name. This means, however, that signals can only live on particular objects. Further, how do normal signals (non-input) look like then? Also, you want to be able to access the signal objects somehow, if only to debug. Also functional does not work naturally. So maybe this is just a variant of B.
  • B: signal objects are somewhere else, e.g. at foo.signals.title. Ugh. Again, asymmetry with plain signal objects (not on a HasSignals instance).
  • C: There are no properties foo.title('new title') sets the signal. I need to get used to this idea, but I think it can work. A benefit is that it allows for method chaining: foo.title('new title').color('#f00').

Another benefit of C is that it becomes trivial to feed a signal output into an input. Maybe like:

self.valid_input.react(self.okButton.enabled)
self.invalid_input.react(signals.not(self.okButton.enabled))
# or feed, connect, ...?

Decorators

We specify a handful of decorators.

# For input, the function is used to clean/validate the input
@input
def title(v):
   return str(v)

# Normal signals have input signals and yield one signal
@signal('signal_a', 'signal_b')
def signal_absum(a, b):
   return a + b

# React signals get run on signal changes. They are (usually) end-points
@react('signal_absum')
def show_ab(v):
    print('the sum of a and b is ', v)

Shorter syntax?

We could allow this:

class Foo(HasSignals):
    title = Input(check_str)
    # or even
    title = Str()
    # and also
    title_lower = Signal(lower, ['title'])

... but then we need a metaclass to set the name at the class descriptor signals. If we stick to decorators, its more consistent and we don't need a meta class. Let's go with that for now. if ppl really want it, we can refactor to make use of a meta class.

Missing requirement: tornado?

Hi,

I tried testing the example from the readme in a (fresh) virtualenv:

pyvenv flex.test
./flex.test/bin/pip install ./flexx.git # Same result if pulling from pypy with "pip install flexx"
cat <<eof > ex.py
#code from readme omitted
eof
./flex.test/bin/python ./ex.py
Traceback (most recent call last):
  File "ex.py", line 1, in <module>
    from flexx import app, ui, react
  File ".../flex.test/lib/python3.4/site-packages/flexx/app/__init__.py", line 61, in <module>
    from .proxy import run, start, stop, init_notebook, call_later
  File ".../flex.test/lib/python3.4/site-packages/flexx/app/proxy.py", line 10, in <module>
    import tornado.ioloop
ImportError: No module named 'tornado'

Added tornado to install_requires (I use mercurial hg-git):

$ hg diff -c -1
diff -r d14c42b51483 -r 55b0b4821a5c setup.py
--- a/setup.py  Sat Sep 05 13:57:35 2015 +0200
+++ b/setup.py  Sun Sep 06 13:33:49 2015 +0200
@@ -63,7 +63,7 @@
     long_description=__doc__,
     platforms='any',
     provides=[name],
-    install_requires=[],
+    install_requires=['tornado'],
     packages=package_tree(name),
     package_dir={name: name},
     package_data={},

Then virtualenv/pip sets things up correctly, and everything works. Does seem to be awfully few install_requires... Is this a TODO-item?

Tasks towards first release and Euroscipy talk

Essential:

  • Make ui work with react
  • "Apps" without ui is now a bit awkward. Lot of boilerplate with the Proxy class (see paired_example and run_python_in_node examples)
  • The paired_example and run_python_in_node examples currently do not work in node
  • PyScript list comprehensions and all buildins
  • Docs for react
  • Update docs for app
  • Update docs for ui
  • rename Paired/Mirrored?
  • Have a simple plot widget
  • Have some functions to do real FRP

Nice:

  • PyScript methods for list, dict, str
  • canvas widget to make sweet visuals
  • Have a working demo on EC2
  • Review + tests for flexx.webruntime
  • Review of flexx.react
  • Review of flexx.pyscript
  • Change my .git/config and do further dev using PR's
  • Setup CI

Logging

Use logging, setup a flexx logger instead of using Python's default logger. Also think about logging messages from JS.

Questions

Hi,

Looks like a great library and trying to feel out the python space for doing this stuff. I'm pretty new to python (and programming) and brand new to web programming so please excuse the following the noob questions as I had already persued the docs.

  1. Is it possible to call arbitrary JS packages like vega from pyscript both in flexx or from python programs?
  2. Can I use flexx as a django frontend?
  3. Can I call use UI components from other libraries like Polymer and Angular?

Thanks!

Use of existing Python-JavaScript tools such as Brython?

This looks like a great project. Looking forward to using it. Just one question. Have you considered using something like Brython for the JavaScript handling instead of writing your own implementation? Having a Python3-only solutions seems fine to me. Do you want to avoid too many dependency? Or does Brython not meet your needs?

Moving forward

Meta issue to collect tasks:

  • Review all the code (already did a first sweep, but need another)
  • Better test coverage
  • meta-tests to verify that nothing more is imported than intended
  • CI
  • test visual result #133 #12
  • More widgets (e.g. treeview) #111
  • High-level fool-proof layout widgets (think dashboards) (there is plotLayout, but I do not like it too much
  • widget.flex signal should be a tuple
  • Multilingual support (i.e. translations, and tools to do translations) #138
  • Themes #139
  • PyScript methods for list, dict, str
  • Easy to use canvas widget
  • More formal communication protocol (binary) #65

Python 3.5 compatibility broken

When using Flexx with Python 3.5:

$ python ../signage/demo.py 
Traceback (most recent call last):
  File "../signage/demo.py", line 1, in <module>
    from flexx import app, ui, react
  File "/home/chris/signage35/lib/python3.5/site-packages/flexx/app/__init__.py", line 61, in <module>
    from .proxy import run, start, stop, init_notebook, call_later
  File "/home/chris/signage35/lib/python3.5/site-packages/flexx/app/proxy.py", line 17, in <module>
    from .clientcode import clientCode, Exporter # global client code
  File "/home/chris/signage35/lib/python3.5/site-packages/flexx/app/clientcode.py", line 48, in <module>
    @py2js
  File "/home/chris/signage35/lib/python3.5/site-packages/flexx/pyscript/functions.py", line 73, in py2js
    p = Parser(pycode, **parser_options)
  File "/home/chris/signage35/lib/python3.5/site-packages/flexx/pyscript/parser0.py", line 190, in __init__
    self._parts = self.parse(self._root)
  File "/home/chris/signage35/lib/python3.5/site-packages/flexx/pyscript/parser0.py", line 340, in parse
    res = parse_func(node)
  File "/home/chris/signage35/lib/python3.5/site-packages/flexx/pyscript/parser1.py", line 553, in parse_Module
    code += self.parse(child)
  File "/home/chris/signage35/lib/python3.5/site-packages/flexx/pyscript/parser0.py", line 340, in parse
    res = parse_func(node)
  File "/home/chris/signage35/lib/python3.5/site-packages/flexx/pyscript/parser2.py", line 770, in parse_ClassDef
    if node.keywords or node.starargs or node.kwargs:
AttributeError: 'ClassDef' object has no attribute 'starargs'

See this issue for details on the backwards-compatibility breakage in Python 3.5 with an attached patch they used to fix it.

Host flexx apps on Amazon ES2

  • Make it possible
  • Host a flexx server with a couple of apps

(the free tier gives you 12 months free use (720 hours, which is fulltime) of a simple server.)

Pyscript should have a (virtual) namespace for JS stuff

There are two common problems with PyScript:

  • PyFlakes complaints about the use of undefined variable names. I tried to remedy this by allowing some dummy names to be imported from flexx.pyscript, but of course there is plenty of other stuff in JS.
  • People who see a piece of PyScript are easily confused when they see Math.X instead of math.x, etc.

Proposal: Allow a stub from flexx.pyscript import X, and inside pyscript allow writing X.Math.pi X.undefined, X.window, etc. The transpiler will simply remove X. wherever it is used.

For the name, it should be short but unique enough. Maybe JS, js, root, jsroot, __root__ ...

Integration with tools like Blaze, Bokeh, Vispy

Have you considered Blaze or Bokeh integration? Not sure if this is to be data focused, but integration with those tools could be really cool, ala R's shiny but more flexible and powerful.

Escher is a similar Julia project, using reactive programming, that might yield some ideas.

How to write custom widget definitions

Currently, Flexx allows writing widget hierarchy like this:

with SomeLayout():
    with SubLayout() as layout:
        b1 = Button()
        b2 = SomeWidget()
    b3 = ProgressBar()
    ... etc.

I like how it is a declarative style, which shows the structure of the app. However, not everyone might like it as much. Some feedback should be collected.

Another approach could be:

b1, b2, b3 = ...
SomeLayout(SubLayout(b1, b2), b3)

If we change layouts to not be widgets, that would have implications on this topic (#9)

Flexx looking for Chrome on linux in /usr/lib

When trying to use the Chrome runtime on Linux I was getting:

RuntimeError('Chrome or Chromium browser was not detected.')

chromeapp.py is looking for Chrome and Chromium in /usr/lib for some reason:

elif sys.platform.startswith('linux'):
    paths.append('/usr/lib/google-chrome/google-chrome')

I don't know of any distros that will be keeping the browser binaries in /usr/lib. Furthermore, the Chrome binary filename should also include the channel. That is: google-chrome-stable, google-chrome-beta, google-chrome-dev.

I fixed the path in chromeapp.py and it's working great.

Changing the above code to:

elif sys.platform.startswith('linux'):
    paths.append('/usr/bin/google-chrome-stable')
    paths.append('/usr/bin/google-chrome-beta')
    paths.append('/usr/bin/google-chrome-dev')

...should support the vast majority of modern distros and all of the Chrome release channels one may have installed.

The same fix should be applied to the Chromium detector function with appropriate file names.

Layout margin is really padding -> rename

The margin property of e.g. the HBox was taken from Qt layouts. However, its implemented with css-padding, so the term is confusing, especially to web devs. We should rename.

Command line interface

Use cases:

  • Control a running flexx process, can be usefull to shutdown the aws server that runs in screen.
  • For live develop mode (#8).
  • Converting an app to html
  • As an alternative for starting or serving an app (e.g. flexx serve foo.py will serve all widgets defined in foo.py).
  • Generating js and css that provide the JS side of flexx.

How should apps work?

Modes

We need a few modes of operation:

  • App mode: Create app classes that get hosted to multiple clients; one app instance per client. Multiple app classes can be served from one process. An app class consists of a subclassed Widget, which is decorated. Such "app-widgets" have a launch() and export() method.
  • Interactive mode: Simply created widgets get associated with a "default clien". This client gets launched as soon as the first widget is created. Call xx.run() to start serving the runtime. When tornado is running, the app is responsive immediately (no need for xx.run()).
  • Notebook mode: Similar to interactive mode, except that a created widget is shown in the output after the cell where it is created. Need some xx.run or xx.start() at the beginning to initialize Flexx. Ideally, the output should be such that the widgets remain visible when the notebook is exported (and have JS callbacks working too!).
  • Hybrid: You should be able to host apps, and at the same time show widgets interactively in the "default client".

References

In Qt:

class Main(QtGui.QWidget):
   ....
app = QtGui.QApplication([])
m = Main()
m.show()
app.exec_()

In Tk:

class Main(Frame):
    ...
m = Main()
m.mainloop()

In Vispy:

class Main(app.Canvas):
    ...
c = Main()
app.run()

In Kivi:

class Main(App):
   ...
m = Main()
m.run()

Support legacy Python (py 2.7)?

Via six.py or python-future.org

I'm a bit tired of making stuff work on both Python2 and Python 3. I just want to write isinstance(c, str). But maybe to get Flexx out there and usable from existing projects, I'd have to give in. We'll see.

PyScript support is the trickiest bit, I suppose, because the ast parser behaves slightly different. But the ast parse of pypy is different too, and I very much like to support that. Having a pure Python ast parser would be even more awesome, see #19.

Integration with cyclepy

I made a quick python port of cycle.js here at cyclepy. I did this mostly just as an exercise. When I saw you project I wondered if it would be possible to use it to somehow to update the ui.

Do you think this would be possible?

Random session id

Making an issue so that I wont forget. Session id's are now set using the id() of the session object (i.e. its position in memory). This might be a secutity hazard. Instead the id should be a randomly generated string.

Formalize the communication protocol (no more eval)

Right now, for some stuff the Python side sends JS over that is eval'ed at the client. I'd like to move to a more formal protocol, and have an explicit entry point for this, to allow using the JS side of Flexx from other systems. In other words, all JS widgets (as written in PyScript) can be used using a completely independent Python library. Or a Julia library, or a JS library...

One use-case I have in mind that if there were a visualization library based on Flexx, it could be compatible with a standardized visualization protocol.

Also, maybe the protocol should be binary, to send data more efficiently, e.g. for visualization. A downside of that is that exported apps would need base64 encoding, or can we put the list of commands in an external (binary) resource?

Layouts should perhaps not be widgets

I initially thought that layout being widgets made things simpler, and it also felt natural because layout are html elements too. However, it makes things less flexible. As Chris put it:

An *extremely* simple case is toggling the layout based on the width
of the parent. This can be changing the orientation of a box layout
or switching from a wrapping flow layout to a vbox layout or
something else.

A more complicated case arises when you build an app which hosts
user-defined content. In these cases you'll typically provide a
widget to user code to use as a host for the user content (which
you know nothing about). If layouts are separate from widgets, you
can just provide an empty widget and the user can assign whatever
layout they please. If not, you have to just choose a host widget
like a VBox, and if that's not what the user wants, they have to
add another level of nesting to achieve their desired layout.

Also interesting: in both Qt and wx, a splitter is a widget, but hbox is a layout. In Qt there is the QStackedLayout, but also the QStackedWidget as a convenience.

Disadvantages of Layouts being widgets:

  • Deep hierarchies. In a custom widget, the self._some_widget.parent will typically not refer to self, but to a layout. To get to self, you may need to .parent several times. This is not a performance thing, because regardless of what we choose, the nesting is this deep in the DOM. It's about how the gui hierarchy feels to the user.
  • The hierarchy (and possibly depth of nesting) changes when you change the layout; you cannot rely on a widgets position in a hierarchy. But maybe you also shouldn't.
  • Toggling the layout of a widget is possible, but a bit awkward.

Disadvantages of Layouts being separate:

  • You have two systems, two hierarchies that are separate, but not quite.
  • If I dynamically add a widget to a custom widget, I need to also add it to the hierarchy, whereas with Layout-Widgets you can just do someWidget.parent = myWidget.hbox.

PyScript: should operators behave as they do in Python?

Pre: the difference in behaviour of operators is the main JS that "leaks" through in PyScript. Fixing this, would make PyScript even more Pythonic.

Con: this would require a function call everywhere where an operator (like add and mul) is used (like in Batavia: https://github.com/pybee/batavia/blob/master/batavia/utils.js#L210). In tight loops this hurts performance.

Idea: Maybe implement that, and allow a context manager where we have more raw JS (disabling PyScript's smart stuff).

Support for some form of live reload

Like running flexx serve, and upon saving the file that defines your app, it gets automatically reloaded in the browser, preferably with state (i.e. what tab is open) preserved.

A PyScript shell in the browser (i.e. PyScript support eval)

If PyScript can compile itself, we can generate a JS implementation of the PyScript transpiler, which means we can allow people to write PyScript directly in HTML docs, support eval(), and have a PyScript terminal. Sweeeet ...

To get there:

  • Probably make PyScript a bit more Pythonic (e.g. operators). At least enough to ...
  • Run PyStone on PyScript.
  • We need a pure Python implementation for the ast module (#54).
  • All of the PyScript transpiler must be made pyscript-compatible.

This functionality is not really necessary from the point of view of flexx.ui, but it would open a lot of new possibilities, and brings PyScript into the same ballpark as Brython and Skulpt.

Getting Flexx to a first working version

This is a meta-issue to list the tasks necessary to make Flexx actually work. The plan is to first stick to a very basic but working version, get testing up and running so that it keeps working, and then extend from there.

Functionality required:

  • A property system ala HasTraits that syncs Python objects with their corresponding JS objects.
  • PyScript: conversion of Python to JS
  • Run apps in the browser
  • Run apps in a desktop-ish environment
  • Create widgets in Jupyter notebook (and have it stay working when statically served)
  • Documentation (API reference, very basic tutorials)
  • Basic event system
  • A few more widgets (checkboxes, list views, stuff standard in HTML)
  • Layout widgets. I believe that the approach for doing layout in Flexx results in very natural flow. I want to demo it (or be challenged with a use-case and see that it fails).

Next steps (these points should probably become standalone issues at some point):

  • More tests, CI, test visual result.
  • More widgets (e.g. treeview)
  • More fancy demos
  • High-level fool-proof layout widgets (think dashboards)
  • Multilingual support (i.e. translations, and tools to do translations)
  • Revisit communication protocol

Support building UI's in other languages

Some projects currently going on (like Jupyter widgets, IBM's work in the notebook, Bokeh apps), target multiple kernel/server languages. Flexx is rather bound to Python, though in principal it should be possible to target languages as well, if we formalize a good client-server communication protocol. Collecting thoughts on this here.

It might be possible to auto-generate e.g. Julia code from the Python implementation. The JS code is already there, though users must be able to write client code as well.

Any target language would need:

  • A websocket implementation
  • An implementation of react that is compatible with our Python and JS version.
  • A way to let the user write JS, preferably in the target language, but this might be difficult for e.g. Julia, because it might not map so well to JS as Python does.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.