Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Eel 1.0 #88

Closed
ChrisKnott opened this issue Dec 9, 2018 · 13 comments
Closed

Eel 1.0 #88

ChrisKnott opened this issue Dec 9, 2018 · 13 comments

Comments

@ChrisKnott
Copy link
Collaborator

ChrisKnott commented Dec 9, 2018

Over Christmas I am planning to put some hours into cleaning up Eel and pushing to a 1.0 release, which should be bug free and stable for a while.

I am opening this issue so that people can suggest/request features or design changes.

Stuff I can think of;

  • Renaming exposed functions. I think this is half implemented. You should be able to say eel.expose(actual_function, 'exposed_name').
  • First class Electron support.. It should be easy to use Electron as browser, not have to use 'custom'.
  • Better packaging as standalone app. There seem to be a few issues people are having with pyinstaller. This process could be polished.
  • Better docs/tutorial/examples/wiki.
  • Jinja2 templates support. Have had PR sitting there for this for a while, I will integrate it
@brumar
Copy link

brumar commented Dec 10, 2018

This is all I can think of. This is rather a long list, sorry about that. I hope my enthusiasm is not asphyxiating. If you are willing to discuss some points, maybe we could exchange on dedicated issues or create new ones to avoid polluting this thread. I worked on some of these items on my repositories so I can help on them if needed or submit precise PRs. I tried to order my list by decreasing order of priority.

  • Support python 3.7 => find what's wrong with pyinstaller and the most recent gevent version
  • Support async and generators "return" values (both on js and python side) or indicate on the readme that it's not supported at the moment.
  • Now, for what concerns iterators, maybe one should keep the "return me everything when it's done" like I did on my repository, but providing a way to implement the iterator protocol instead of returning the whole list of values could be nice.
    so that, if, for example, eel.function is a generator on the js side, maybe one could process values one by one with something like that :
for i in eel.eelterator(eel.function(input)):
	print(i)

Instead of the classical version which would consume the whole iterator.

for i in function(input)():
	print(i)

But I don't know how to achieve that since the values of "function" comes from another source. It seems to be a way to achieve this using RxPy and asyncio but that's a lot to buy (https://github.com/ReactiveX/RxPY/blob/master/examples/asyncio/toasyncgenerator.py).

  • Setting timeout like with eel.set_timeout_js(timeout=5) would seem nice to me. Exposing an hook would be nice to eel.on_timeout_js(callback) would be nice too.
    maybe a decorator would be nice to get a "local timeout" with eel.timeout(12, raise_timeout_exception=True): But I think that would require to add a field in the call object, because with this async framework, I don't know if this is right to mess with a global value temporally.
  • gives more control on the user for the parsing of static files (which is a bit brittle and implicit), or even remove entirely the parsing of static files, by getting this information ASAP from querying eel. I personally don't like eel.expose(func, funcname) as funcname has no strong reasons to be another thing than func.name.
  • Use the logging library so that users can debug eel more easily.
  • Eel should be able to know about javascript errors, maybe by sending stuff to python with window.onerror (cf this one : https://stackoverflow.com/questions/11257330/error-logging-for-javascript-on-client-side). That would allow more efficient development and testing, as well as opening up the possibility of a dedicated hook to grab these errors like on_js_error(func).
  • For the development of Eel itself, I think that's really cool to submit PR along with tests that deals with the feature and the bugfix. This ease the burden of testing manually if the PR is not buggy somewhere. I'd suggest to use :
    • selenium tests (with pytest maybe?)
    • getting a CI pipeline for the development (travis? Jenkins?)
  • On the documentation, maybe getting clearer or what can or can't be passed from one side to the other (inputs must be JSON serializable I guess)
  • Hooks for objects that are not JSON serializable.
    eel.register_json_hook(MyClass, boundmethod).
  • Maybe drop the execs in init.py. I believe that setattr(sys.modules[__name__], funcname, func) would work equally well.
  • Raise an Exception if an exposed python function has the same name of an eel method.
  • Allow to use the await keyword on the python side. But hat would require to either replace bottle with another websocket friendly python async framework (Sanic maybe?) or to use aiogevent to get wrap gevent into asyncio API (https://github.com/2mf/aiogevent) but it seems a bit foggy.
  • debug interface in the browser (for example to know which functions are exposed and to manually call them)
  • Build an attractive example by stealing a nice looking frontend somewhere.

@alxliv
Copy link

alxliv commented Dec 29, 2018

Second Brumar on python 3.7 support. Also please make monkey patch optional (or fix it somehow)- it does not work under Windows 10 - raises strange exceptions.
I had to manually comment out line 3 in eel init.py:

# import gevent.monkey as mky; mky.patch_all()

to make eel work. Other than that, it is an excelent library and is very useful for my purposes.
Thank you and keep up the great work!

@ChrisKnott
Copy link
Collaborator Author

@alxliv I pushed a quick update to remove monkey patching. Sorry about that, stupid decision.

@brumar I've looked over your repos and it looks good. I've added you as collaborator as you have demonstrated a full understanding of how Eel works (and how it could work better!). For bug fixes and minor changes, feel free to change and push directly. For changes such as migration to Sanic make a new branch and we can discuss it before. I will focus on Electron support and improvements to packaging.

I don't have enough time to support Eel as much as it deserves so I think it is important to add more collaborators. The BigQuery estimate of PyPI downloads is up to ~7000 a month, with a lot of interest from Python newbies.

@ahopkins I never said - thank you for mentioning Eel on Talk Python To Me!

@brumar
Copy link

brumar commented Dec 31, 2018

@ChrisKnott Wow I did not expect that, thanks for adding me in, I am really honored 😳. Yet it's one thing to have fun with forks and suggestions, it's another to to have real responsibilities. I hope I won't break anything (even for minor changes). I'd like to add tests before doing something wrong. Under one of my repositories, I have a Jenkins Pipeline based on docker which run tests (among them, selenium tests on the built produced by pyinstaller). Maybe that could be adapted there to ensure at least that examples still work. If so, that would be great to migrate the pipeline to travis.ci but I think I'd be too lazy for that.

Also that's not really true that I have a full understanding on how eel works, there are some parts that are still a bit mysterious to me.

@ahopkins I also listened to this episode (well, all episodes of any production of Michael Kennedy and Brian Okken anyway). After this episode and after having checked that Sanic was supporting websockets, I though it could replace bottle here. My main motivation for that is to get async/await working. What's your mind on this idea ? Did you hear of any success with pyinstaller ? I also heard good things about aiohttp (and it supports websockets too). Maybe that would be a lighter option ?

@PFython
Copy link

PFython commented Mar 24, 2019

Hi Chris - probably the wrong place but just wanted to post a note of thanks as a Python newbie myself. Eel is a really amazing thing and I find myself working with it constantly.

Maybe I overlooked it or maybe it's just not built to allow this, but is there an easy way of using the standard Bottle @route("/otherpage") routing in the same script as all the nice Eel stuff? I've tried and failed to add something like:

import eel
TEMPLATE_PATH = eel.btl.TEMPLATE_PATH
template = eel.btl.template
route = eel.btl.route
eel.init('web')

# Setup bottle templating
if(sys.platform == 'win32'):
    templates_dir = os.path.join(dir_path, 'web')
    if templates_dir not in TEMPLATE_PATH:
        TEMPLATE_PATH.insert(0, templates_dir)

...

@route("'/login'")
def login():
    return (template("my_login"))

before eel.start() ...but no luck. I just get:

Error: 404 Not Found
Sorry, the requested URL 'http://localhost:8080/login' caused an error:
File does not exist.

I think other newcomers will also be wondering if this is possible, and if so, how, so would love to see an update in the docs/examples at some point.

Many thanks and best of luck with the project,
Peter

(Also London based, in case you ever fancy a coffee/drink away from the computer!)

@samuelhwilliams
Copy link
Collaborator

Hi @PFython

I just tried this out with a very simple pair of files, and it seems to work fine:

main.py


import eel


eel.init('web', allowed_extensions=['.js', '.html'])

@eel.btl.route('/test')
def test():
    return 'hello; successful test'

eel.start("main.html",)

main.html

<html>
    <head>
        <title>Hello, World!</title>
        
        <!-- Include eel.js - note this file doesn't exist in the 'web' directory -->
        <script type="text/javascript" src="/eel.js"></script>
    </head>
    
    <body>
       <a href="/test">click this link</a> 
    </body>
</html>

It worked fine. From your example, you have done @route("'/login'"). If this is verbatim from your source file, the problem is probably that you've got double and single quotes around /login. So the route is likely invalid.

@PFython
Copy link

PFython commented Mar 24, 2019

Thank you so much @samuelhwilliams - what an idiot I am! (blame it on late night copy/paste...).

It works for me too now which is brilliant. I didn't actually even need to add allowed_extensions=['.js', '.html']).

I repeat my suggestion @ChrisKnott to explicitly add a short mention of this to the Readme, not only for newcomers like me for whom this might not be obvious, but because it's actually a great 'selling point' for Eel that you can do all (?) of the normal Bottle things in Eel as well as the Eel-specific things.

In fact it makes me wonder why anyone would want to just use Bottle instead of Eel...

Best wishes,
Peter

@ethanpil
Copy link

Just pinging here to get an update on v1...

@PFython
Copy link

PFython commented Mar 30, 2019

Probably more of an enhancement for Bottle, but since it looks like you're more active Chris, it would be nice to offer a helper function/alias/decorator option for:

print(eel.btl.request.route.rule) # Current route - useful for debugging
and
print(eel.btl.request.route.app.routes) # Print all currently loaded routes

These are buried in Bottle and therefore further buried in Eel, not documented in Bottle and even after searching stackoverflow the accepted answer didn't work right out of the box for me. If you could offer an option in the @route / @get etc. decorators or eel.start() options to echo one or both, or just give these attributes a helpful name and mention it in the docs, that would make Eel even more beginner friendly and (sorry if I'm planning for Eel to take over the world without asking you!) give it much broader appeal especially to Python newcomers like me - Eel as the new Bottle??!

@samuelhwilliams
Copy link
Collaborator

I've currently sort-of shelved an official v1.0.0 release at the moment, for a couple of reasons:

  1. API stability: I'm not sure our API is really that stable or considered yet, and I'd like to give it a bit more time to settle and work out kinks.
  2. Tests: we don't have any automated tests, and the risk of introducing regressions with the current code structure is high. I'm finding it difficult to come up with a clear (functional) testing plan, which is currently a bit of a blocker. I will start adding unit tests soon, but to me the project could do with quite a bit of refactoring in order to create clean, testable units.
  3. There's unlikely to be any greater level of stability simply by publishing a v1, but people will expect that based on an official "major" release. So I'm not rushing to do it just for the sake of it. I believe most of Chris's features are currently in place on the latest v0.x (v0.12) release, so if people want those features then they should please consider trying them as-is without waiting for v1.

@ChrisKnott
Copy link
Collaborator Author

What is your obsession with high quality code 🤣.

I originally wanted to get breaking API changes out quickly to minimize disruption, but user growth is fairly steady https://pypistats.org/packages/eel so I don't think there's any rush, and it is better to take the time to make structural changes if it will allow long term health of the project.

@brumar
Copy link

brumar commented Dec 8, 2019

Hello, sorry to join the conversation after one year of inactivity (and probably more to come). With respect to my laziness, please take my input with a grain of salt ^^'.

Functional tests would be awesome, that would be very useful for PRs and reproducing bugs. More than that, it could empower eel users to automate their cross-platform builds. In one of my experimental forks, I toyed with the blue ocean jenkins docker image. It worked reasonably well and produced windows and linux builds tested with selenium web browser. If you like the idea, I can try to do a PR on the subject before 2020. I am not a CI expert, and maybe there are more modern & practical alternatives.

I saw in an issue that an user managed to get async/await working on the python side using asyncio instead of bottle (if I remember well). This would be an highly justifiable breaking change in my opinion. Async & await is where the fun is, and being a bit more symmetric with the js side would be great.

@samuelhwilliams
Copy link
Collaborator

I'm going to close this down for now as it's an old v1.0.0 thread that isn't really relevant at the moment. I'll open a new one when we start considering a v1.0.0 release again.

Support for async is definitely something on my radar and I think @ChrisKnott has done some exploratory work around it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants