manatlan / guy

Graphics User Ynterface : a simple module for making GUI applications (with html/js) for py3 ... to target windows, linux, mac & android
Apache License 2.0
202 stars 23 forks source link

How to call function on client from server? #5

Closed johannes-luebke closed 4 years ago

johannes-luebke commented 4 years ago

I am trying to replace the eel package with the guy package. One thing I can not understand from the documentation is how I would go about calling a function on the client (javascript) from my python backend. So what I am trying to do is: Python:

def print_on_client(message):
    guy.call("print", message)

print_on_client("hello world")

Javascript:

function print(message){
    console.log(message);
}

I would expect the client printing "hello world" in the console. What would be the correct way to achieving this?

manatlan commented 4 years ago

Not like eel ...guy doesn't provide a way to call (rpc) the client directly. In the guy's world : it's a non-sense, because guy can be runned in served mode (1 server + many clients). But guy provides another mechanism : the pub/sub ... client must subscribe/listen to an event ... and server (or other clients) can publish an "event" ...

See : https://github.com/manatlan/guy/blob/master/testPyInit.py ... you can replace the self.emit(), by self.emitMe() to send the event, only, to the connected client ...

BTW, I don't see any real life need to implement this kind of thing (i'd like to hear ones) ... and BTW2 : it could be really easy, for me, to provide a layer on top of this (pub/sub) to provide this kind of thing, in a near future.

johannes-luebke commented 4 years ago

Thanks for the answer. I assumed it would be a different approach its just in my current eel version of my app I have a lot of back and forth with js calling python and python calling js. I just wanted to know if there is a way to convert the code easily.

I will see if I can rewrite my code with this different approach. Just one more question - is my understanding correct that this doesn't work:

async def test(self, message):
    await self.emit("print", message)
test("hello world")

and always needs this:

async def test(self, message):
    await self.emit("print", message)
asyncio.ensure_future(test("hello world"))

So everytime I want to call a function from python I need to start a coroutine? Sorry for the questions I am new to working asynchronous

manatlan commented 4 years ago

Not like eel ... A guy's app is a python's class ... (Every method declared in the class is exposed in client side (as js method)) If you are in the python's method (so, in the server main's loop), you don't need to start a couroutine. Mainly, you don't need to start a coroutine, because all your code will be in the guy's class. (think that the class is the mirror/proxy of the client, there is an independant instance by client... because there can exists multiple clients (in server mode only))

If you need to put your interaction outside of the class : you've got a trouble of design ... and you loose the context (1 client == 1 instance class), and you should manage yourself which client for which instance ... (but depending on your need : it can work ... but not with guy's full power)

If you got a (simple/short) eel's app ... I can show you how it will be in a guy's class ... no problem You will understand quickly (i'd like to do this exercice)

manatlan commented 4 years ago

Btw, to clarify my explanations ...

Here is the eel's "hello world" : https://github.com/samuelhwilliams/Eel/tree/master/examples/01%20-%20hello_world

And here is the guy's version of ^^: https://github.com/manatlan/guy/blob/master/testEelHelloWorld.py

Both are doing the same thing ...

the guy version is all in one file : the html/js and the python ... but you could put the html/js in a "static/Hello.html" file, it's the same thing.

johannes-luebke commented 4 years ago

Thank you very much for clarifying @manatlan! Unfortunately when I just copy the code from: https://github.com/manatlan/guy/blob/master/testEelHelloWorld.py I get this result in the python console:

\.pyenv\guytest\lib\site-packages\guy.py:617: RuntimeWarning: coroutine 'Hello.init' was never awaited
  new.init(new)
RuntimeWarning: Enable tracemalloc to get the object allocation traceback
Hello from Javascript World!

and the browser window only says "Hello from Javascript World!" I got that message with all my tests before so I thought I might be doing something wrong but now I don't know anymore. Any Ideas?

manatlan commented 4 years ago

Just update your guy package to 0.4.2

Le ven. 31 janv. 2020 à 23:04, megohannes notifications@github.com a écrit :

Thank you very much for clarifying @manatlan https://github.com/manatlan ! Unfortunately when I just copy the code from: https://github.com/manatlan/guy/blob/master/testEelHelloWorld.py I get this result in the python console:

.pyenv\guytest\lib\site-packages\guy.py:617: RuntimeWarning: coroutine 'Hello.init' was never awaited new.init(new) RuntimeWarning: Enable tracemalloc to get the object allocation traceback Hello from Javascript World!

and the browser window only says "Hello from Javascript World!" I got that message with all my tests before so I thought I might be doing something wrong but now I don't know anymore. Any Ideas?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/manatlan/guy/issues/5?email_source=notifications&email_token=AABEZQRRVP3IDCQ67ADXXBDRASN6VA5CNFSM4KMFINV2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEKQEZXQ#issuecomment-580930782, or unsubscribe https://github.com/notifications/unsubscribe-auth/AABEZQQNMKIRAYKXTQ574ITRASN6VANCNFSM4KMFINVQ .

johannes-luebke commented 4 years ago

Perfect now it works! Thanks for the help, now I understand the logic.

manatlan commented 4 years ago

Stay tuned ...

coz, the next version will implement a way to call directly a js method ... from py side, without using events (I'm making a layer on top of that, to abstract the concept)

you could use :

    await self.js.say_hello_js("Python World!")

in place of :

    await self.emitMe("say_hello_js","Python World!")
manatlan commented 4 years ago

The 0.4.3 is here ... See : https://github.com/manatlan/guy/blob/master/testEelHelloWorld.py

I will update the doc ;-) ... it's a nice feature