From 6d0f7e7f0584f3d6d1c8932fa6c6eba701022a6e Mon Sep 17 00:00:00 2001 From: evandrocoan Date: Mon, 22 Nov 2021 23:18:32 -0300 Subject: [PATCH] Fix issue 1362 and add a default favicon.ico (#1369) --- qt/aqt/data/web/imgs/BUILD.bazel | 1 + qt/aqt/data/web/imgs/favicon.ico | Bin 0 -> 4286 bytes qt/aqt/main.py | 1 + qt/aqt/mediasrv.py | 58 ++++++++++++++++++++++++++++++- 4 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 qt/aqt/data/web/imgs/favicon.ico diff --git a/qt/aqt/data/web/imgs/BUILD.bazel b/qt/aqt/data/web/imgs/BUILD.bazel index 58b338198..26b6d5efd 100644 --- a/qt/aqt/data/web/imgs/BUILD.bazel +++ b/qt/aqt/data/web/imgs/BUILD.bazel @@ -1,6 +1,7 @@ filegroup( name = "imgs", srcs = glob([ + "**/*.ico", "**/*.png", "**/*.svg", ]), diff --git a/qt/aqt/data/web/imgs/favicon.ico b/qt/aqt/data/web/imgs/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..257849bdc2f34b4a14b3d947646b7d706f38bc5e GIT binary patch literal 4286 zcmcJSc}x^{6vqc+nwSPbo7OZosef48X8vgVr)d+s5byiOTf7nQM!Xg83opd`DhM9b zrb-Kc6ice2C}Qgft+tAS3oOU3%d(t)`@TOjWP>p~m~_coHoG(PnfKoJ9iwS}^4Fz{ z#&<0_P}4rrH0=v9`AX{{#_!cje*574*Y^4gOYd@))>TY@2kR#1_>1|8wf5CcP6!jr z5X%)a-of(ZoHVfrvDVx}yEbjwTvM(o?S4}16S#hyKTuzUAz?A*B% zJ9g~Awr$(6b?a7a-nVJZrHE^YuB#D;>C+Gc<^Azbs+pCu@A+pyu!#{x^!tX z_t2q3ID7W2;Oh{`t|FvZrwVpS+fSKR;|Lyl`FAg#R|-xJsa)Yw|5IT+yb2W z&X_iBTC=~qcI`rDW+q;}YJ%NvM`~)S@|Rrtx@F5296fqe8QCT`IyxH5mMsJQ7%*S} z+O}7$>E)G|(UPXR>J{%4QoKB~@ z7n8eW$r6==g$oyA?AWpJ_xE>M;8W)YV@xh{OaE@)zKzD3a?})N!Bd=rCXWNJ8tc&T zvIw4{o2dTlM>N(tl^)1lv}h5?jf{*$L_`E8OqhU<9XnD7zFvxNa;YiC`TF(iXsouO zx*!#8I`}sDu3Pp{?SxpA-}npuXY}sV}$J=l^$;HoNBb!l=#LqnDJ`}gmUPMtbg=2OS) z8|(omPMlC0a8y;|W!`Z-OZXB`_kNPr8>^JCxO$<7XNiYAJRijb9+g=^QYDZ6;_qB@VfF=NJnaag{5 zx$2GVmA;B!epmJH&7C`UuBsu{md8~NTgo8O-VoHgO4Q6@e%W8fj~}o6B$uDrgZA&= zkJG15H}__%eDB(&mN^Hhsav;hq59!@)Yu>4(xpppaH)0XjkR;;%o&_IbqXg>o92PUkw-1_9ym`p zlT2UfFMZ_`VHvVZ#j0cAn1|l0^-h@ilYG-^gd5biI_l zz*&w)sfoI>2WlTkOG{I1#)^9pHRX#h+SNrzhPQUTb>y8>#-Fj}4#HYgv)M?IS$qk# zw!3I_m%(PUsrz5OdbNtDFTQ9?7fl&ve3?`B9qNcR#GHEXqKq$h(h^%S+<#w@eIQQt zCD+3XYB$Nxf2fXU?J=jm_>yZ~`kmp6Y3`tmE%zjMRk7L)IIAi$V^j`q+_=%akFxft zU0;0Zb-I|rnla<+y>pXAEqm|Vyw_I^HE5`Mf;#65xc|+7r}P056BC>FVD<*~3SWHb zbzNm&$R)?z^UXcbo5@~o?kLR1xpU`KZg}j?n>SHfTB5Ye{hPJJ+8aK6xX=AlYA#Uv zN(T3L`e{B}uztLm+>g1VP*>)z&m5D-@2FGWpSgdthszFbW&hTs*M&*{YvK+-CTr(y zJd;TuIp<6s<4xl;5a;K>fdk!r`}Vc+{Go|X+DX5=BK@z4{gu~l>7yCfmQ3(#4QQlCD3tUiBfqeqW!H*)02FxeY3ByYLwNwUKkaxG=zk0J3iWUn#$_3LMZ zgoGI4pAj4!YzW5?9xbm&j~;13K|v96z1BQ`Hp^7Ffx_)NWXKSmy;1f!UD&#?bz$qm y)rG4IR~N3{yLWG0xO&f?J!##9?ccq7_qVd8Ac7h-?bBLK3!pjvXEQlulKmfS%k(_} literal 0 HcmV?d00001 diff --git a/qt/aqt/main.py b/qt/aqt/main.py index d92db613b..f4c45f484 100644 --- a/qt/aqt/main.py +++ b/qt/aqt/main.py @@ -1680,6 +1680,7 @@ title="{}" {}>{}""".format( def setupMediaServer(self) -> None: self.mediaServer = aqt.mediasrv.MediaServer(self) self.mediaServer.start() + self.mediaServer.wait_start_up() def baseHTML(self) -> str: return f'' diff --git a/qt/aqt/mediasrv.py b/qt/aqt/mediasrv.py index f67df5f44..2e6e3f0c2 100644 --- a/qt/aqt/mediasrv.py +++ b/qt/aqt/mediasrv.py @@ -3,16 +3,20 @@ from __future__ import annotations +import datetime import logging import mimetypes import os import re +import socket import sys import threading import time import traceback +from contextlib import contextmanager from dataclasses import dataclass -from http import HTTPStatus +from http import HTTPStatus, client +from typing import Any, Generator import flask import flask_cors # type: ignore @@ -32,6 +36,18 @@ from aqt.deckoptions import DeckOptionsDialog from aqt.operations.deck import update_deck_configs from aqt.qt import * + +@contextmanager +def http_connection( + *args: Any, **kwds: Any +) -> Generator[client.HTTPConnection, None, None]: + resource = client.HTTPConnection(*args, **kwds) + try: + yield resource + finally: + resource.close() + + app = flask.Flask(__name__, root_path="/fake") flask_cors.CORS(app) @@ -121,6 +137,46 @@ class MediaServer(threading.Thread): except KeyError: pass + def getHost(self) -> str: + self._ready.wait() + return str(self.server.effective_host) # type: ignore + + def wait_start_up(self) -> None: + self.check_server(self.getHost(), self.getPort(), "/favicon.ico") + + @classmethod + def check_server( + cls, + host: str, + port: int, + path_info: str = "/", + timeout: int = 1, + retries: int = 30, + ) -> int: + """Perform a request until the server reply""" + if retries < 0: + return 0 + # https://github.com/Pylons/webtest/blob/4b8a3ebf984185ff4fefb31b4d0cf82682e1fcf7/webtest/http.py#L123-L132 + for index in range(retries): + if devMode or index > 0: + print( + f"{datetime.datetime.now()} waiting media server on {host}:{port}..." + ) + try: + with http_connection(host, port, timeout=timeout) as conn: + conn.request("GET", path_info) + res = conn.getresponse() + return res.status + except (socket.error, client.HTTPException): + time.sleep(0.3) + return 0 + + +@app.route("/favicon.ico") +def favicon() -> Response: + request = BundledFileRequest(os.path.join("imgs", "favicon.ico")) + return _handle_builtin_file_request(request) + def _mime_for_path(path: str) -> str: "Mime type for provided path/filename."