예제 #1
0
    def init_app(self, app):
        ws_route = app.config.get('TURBO_WEBSOCKET_ROUTE', '/turbo-stream')
        if ws_route:
            self.sock = Sock()

            @self.sock.route(ws_route)
            def turbo_stream(ws):
                user_id = self.user_id_callback()
                if user_id not in self.clients:
                    self.clients[user_id] = []
                self.clients[user_id].append(ws)
                try:
                    while True:
                        ws.receive(timeout=10)
                except ConnectionClosed:
                    self.clients[user_id].remove(ws)
                    if not self.clients[user_id]:
                        del self.clients[user_id]

            self.sock.init_app(app)
        app.context_processor(self.context_processor)
예제 #2
0
파일: flask.py 프로젝트: idom-team/idom
def _setup_single_view_dispatcher_route(
        blueprint: Blueprint, options: Options,
        constructor: RootComponentConstructor) -> None:
    sock = Sock(blueprint)

    def model_stream(ws: WebSocket, path: str = "") -> None:
        def send(value: Any) -> None:
            ws.send(json.dumps(value))

        def recv() -> LayoutEvent:
            return LayoutEvent(**json.loads(ws.receive()))

        _dispatch_in_thread(ws, path, constructor(), send, recv)

    sock.route("/_api/stream", endpoint="without_path")(model_stream)
    sock.route("/<path:path>/_api/stream", endpoint="with_path")(model_stream)
예제 #3
0
class Turbo:
    def __init__(self, app=None):
        self.user_id_callback = self.default_user_id
        self.sock = None
        self.clients = {}
        if app:
            self.init_app(app)

    def init_app(self, app):
        ws_route = app.config.get('TURBO_WEBSOCKET_ROUTE', '/turbo-stream')
        if ws_route:
            self.sock = Sock()

            @self.sock.route(ws_route)
            def turbo_stream(ws):
                user_id = self.user_id_callback()
                if user_id not in self.clients:
                    self.clients[user_id] = []
                self.clients[user_id].append(ws)
                try:
                    while True:
                        ws.receive(timeout=10)
                except ConnectionClosed:
                    self.clients[user_id].remove(ws)
                    if not self.clients[user_id]:
                        del self.clients[user_id]

            self.sock.init_app(app)
        app.context_processor(self.context_processor)

    def user_id(self, f):
        """Configure an application-specific user id generator, to allow the
        application to push updates over WebSocket to individual clients.

        Example:

        @turbo.user_id
        def get_user_id():
            return current_user.id
        """
        self.user_id_callback = f
        return f

    def default_user_id(self):
        """Default user id generator. An application-specific function can be
        configured with the `@user_id` decorator."""
        return uuid.uuid4().hex

    def turbo(self, version=_VER, url=None):
        """Add turbo.js to the template.

        Add `{{ turbo() }}` in the `<head>` section of your main template.
        """
        if url is None:
            url = f'{_CDN}/pin/{_PKG}@{version}/min/{_PKG}.js'
        ws_route = current_app.config.get('TURBO_WEBSOCKET_ROUTE',
                                          '/turbo-stream')
        if ws_route:
            return Markup(f'''<script type="module">
import * as Turbo from "{url}";
Turbo.connectStreamSource(new WebSocket(`ws://${{location.host}}/{ws_route}`));
</script>''')
        else:
            return Markup(f'<script type="module" src="{url}"></script>')

    def context_processor(self):
        return {'turbo': self.turbo}

    def requested_frame(self):
        """Returns the target frame the client expects, or `None`."""
        return request.headers.get('Turbo-Frame')

    def can_stream(self):
        """Returns `True` if the client accepts turbo stream reponses."""
        stream_mimetype = 'text/vnd.turbo-stream.html'
        best = request.accept_mimetypes.best_match(
            [stream_mimetype, 'text/html'])
        return best == stream_mimetype

    def can_push(self, to=None):
        """Returns `True` if the client accepts turbo stream updates over
        WebSocket.

        :param to: the id of the client. If not given then the answer
                   is `True` if there is at least one client listening to
                   updates over WebSocket.
        """
        if to is None:
            return self.clients != {}
        return to in self.clients

    def _make_stream(self, action, content, target):
        return (f'<turbo-stream action="{action}" target="{target}">'
                f'<template>{content}</template></turbo-stream>')

    def append(self, content, target):
        """Create an append stream.

        :param content: the HTML content to include in the stream.
        :param target: the target ID for this change.
        """
        return self._make_stream('append', content, target)

    def prepend(self, content, target):
        """Create a prepend stream.

        :param content: the HTML content to include in the stream.
        :param target: the target ID for this change.
        """
        return self._make_stream('prepend', content, target)

    def replace(self, content, target):
        """Create a replace stream.

        :param content: the HTML content to include in the stream.
        :param target: the target ID for this change.
        """
        return self._make_stream('replace', content, target)

    def update(self, content, target):
        """Create an update stream.

        :param content: the HTML content to include in the stream.
        :param target: the target ID for this change.
        """
        return self._make_stream('update', content, target)

    def remove(self, target):
        """Create a remove stream.

        :param target: the target ID for this change.
        """
        return self._make_stream('remove', '', target)

    def stream(self, stream):
        """Create a turbo stream response.

        :param stream: one or a list of streamed responses generated by the
                       `append()`, `prepend()`, `replace()`, `update()` and
                       `remove()` methods.
        """
        return current_app.response_class(
            stream, mimetype='text/vnd.turbo-stream.html')

    def push(self, stream, to=None):
        """Push a turbo stream update over WebSocket to one or more clients.

        :param stream: one or a list of stream updates generated by the
                       `append()`, `prepend()`, `replace()`, `update()` and
                       `remove()` methods.
        :param to: the id of the target client. Set to `None` to send to all
                   connected clients, or to a list of ids to target multiple
                   clients.
        """
        if to in self.clients:
            to = [to]
        elif to is None:
            to = self.clients.keys()
        for recipient in to:
            for ws in self.clients[recipient]:
                ws.send(stream)
예제 #4
0
import image_utils
import json
from PIL import Image
import traceback
import legolize
import palette
import base64
from io import BytesIO
import simple_websocket

logger = utils.init_log()
app = Flask(__name__)
CORS(app)
HOST = os.environ['HOST']
DEBUG = os.environ.get('DEBUG', 'False')
sock = Sock(app)

pal = palette.Palette()

logger.info(f"palette loaded of {len(pal.colors)} colors")


@app.route('/upload/<size>', methods=['POST'])
def upload(size):
    uid = str(uuid.uuid4())
    input_name = utils.input_name(uid)

    file = request.files['file']

    file.save(input_name)
예제 #5
0
logging.basicConfig(level=logging.DEBUG, filename='log.txt', filemode='w', format='%(asctime)s - %(levelname)s - %(message)s', datefmt="%Y-%m-%d %H:%M:%S")
console = logging.StreamHandler()
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s', "%Y-%m-%d %H:%M:%S")
console.setFormatter(formatter)
if args.logging_level == 'info':
	console.setLevel(logging.INFO)
elif args.logging_level == 'debug':
	console.setLevel(logging.DEBUG)
logging.getLogger().addHandler(console)

#-------------------------------------------------------------------------
# Flask server configuration
#-------------------------------------------------------------------------
logging.debug('creating the api flask object')
api = Flask(__name__)
sock = Sock(api)
CORS(api)       # CORS BS that we likely don't need to worry about'

#-------------------------------------------------------------------------
# LED Matrix configuration
# Only load these items if we are not in debug mode
#-------------------------------------------------------------------------
if not args.debug:
	logging.debug('setting up the led matrix options')

	from rgbmatrix import RGBMatrix, RGBMatrixOptions
	sys.path.append(os.path.abspath(os.path.dirname(__file__) + '/..'))
	options = RGBMatrixOptions()

	# Configuration for the matrix. Refer to the rpi-rgb-led-matrix python binding docs for the meanings of each option
	options = RGBMatrixOptions()