brython-dev / brython

Brython (Browser Python) is an implementation of Python 3 running in the browser
BSD 3-Clause "New" or "Revised" License
6.39k stars 510 forks source link

Can you add browser.eventsource to Brython? #954

Closed kveroneau closed 5 years ago

kveroneau commented 6 years ago

I noticed that browser.websockets currently exists, and it's module implementation is pretty simple. Just references the object in the browser. Can a similar module be created to easily utilize SSE(Server-side events AKA EventSource) in Brython? In some cases WebSockets is a bit much, and only SSE is needed. On that note, there are actually quite a few HTML5 features missing from Brython at the moment. I also noticed that Pygame was ported to Brython? Why isn't this being mentioned anywhere, I had no idea that it was possible to use Pygame with Brython. Perhaps some documentation on this would be useful.

Here's the MDN for EventSource: https://developer.mozilla.org/en-US/docs/Web/API/EventSource

Great job with bringing Python to the web, much more polished so far than other similar situations. I hope this project continues development for years to come.

coproc commented 6 years ago

@kveroneau concerning pygame and brython: I tried https://github.com/brython-dev/brython-pygame, but this seems to be very incomplete (and I do not see how this could have ever been running; it does definitely not work with the current brython). When investigating further I found some fundamental problems that will make it impossible to run python code based on pygame directly in brython. Here are two (related) problems:

  1. when loading an HTML image (IMG) the actual loading is delayed into a separate event that is added to the JavaScript event queue. The image (and its attributes like width, height, ...) will only be accessible once your current brython function (blocking the other events in the JavaScript event queue) has finished and the loading event can be executed. Before finishing a brython function of your game you have, of course, to add the next brython function of your game to the JavaScript event queue with something like browser.timer.set_timeout(...).
  2. For a similar reason code like clock = pygame.time.Clock(); while ...: ... clock.tick(60) cannot run in brython. Brython does not support time.sleep(...) because of JavaScript and its event queue. One has to define the main game loop as a function (without while) and put the next call of the main game loop into the JavaScript event queue.

But there is also good news: in brython/JavaScript a lot of low level programming (SDL, double buffering, ...) is not needed and implementing e.g. game graphics in brython/JavaScript is in many respects simpler than with pygame. One rough implementation can be found in this project: https://github.com/asherwunk/pygjs. Another project based on brython and inspired by pygame (but with totally different interface) can be found here: https://github.com/BrythonServer/ggame

PierreQuentel commented 5 years ago

Hi,

Sorry for the very late answer...

All HTML5 features should be supported using the standard DOM API ; I am not sure it's a good idea to provide a Brython-specific module for all use cases.

For EventSource, this example works:

<!doctype html>
<html>
<head>
<meta charset="utf-8">

<script type="text/javascript"
    src="https://cdnjs.cloudflare.com/ajax/libs/brython/3.7.0/brython.min.js">
</script>

<script type="text/javascript"
    src="https://cdnjs.cloudflare.com/ajax/libs/brython/3.7.0/brython_stdlib.js">
</script>
</head>
<body onload="brython(1)">

<div id="output" style="width:10%;padding: 5px;font-family: arial;"></div>

<script type="text/python">
from browser import window, bind, document

evtSource = window.EventSource.new('/cgi-bin/send_msg.py')

@bind(evtSource, "message")
def show_msg(ev):
    document["output"].text = ev.data
</script>
</body>
</html>

with __/cgi-bin/show_msg.py__ as follows:

#!c:/python37/python.exe
# -*- coding: utf-8 -*-
import datetime
import sys

print('Content-Type: text/event-stream\n')
print()
print("event: message")
print("data: {}".format(datetime.datetime.now().strftime("%H:%M:%S")))
print("id:77")
print("\n")
PierreQuentel commented 5 years ago

I close the issue, feel free to reopen it if necessary.