mirror of
https://github.com/rio-labs/rio.git
synced 2026-02-09 07:09:00 -06:00
webview import fixes
This commit is contained in:
@@ -679,7 +679,7 @@ class App:
|
||||
Error messages will be printed regardless of this setting.
|
||||
"""
|
||||
try:
|
||||
from .webview import webview
|
||||
from . import webview_shim
|
||||
except ImportError:
|
||||
raise Exception(
|
||||
"The `window` extra is required to use `App.run_in_window`."
|
||||
@@ -723,7 +723,7 @@ class App:
|
||||
# Problem: width and height are given in rem, but we need them in
|
||||
# pixels. We'll use pywebview's execute_js to find out as soon as the
|
||||
# window has been created, and then update the window size accordingly.
|
||||
def update_window_size():
|
||||
def update_window_size() -> None:
|
||||
if width is None and height is None:
|
||||
return
|
||||
|
||||
@@ -753,13 +753,13 @@ pixels_per_rem
|
||||
|
||||
# Start the webview
|
||||
try:
|
||||
window = webview.create_window(
|
||||
window = webview_shim.create_window(
|
||||
self.name,
|
||||
url,
|
||||
maximized=maximized,
|
||||
fullscreen=fullscreen,
|
||||
)
|
||||
webview.start(
|
||||
webview_shim.start(
|
||||
update_window_size,
|
||||
debug=os.environ.get("RIO_WEBVIEW_DEBUG") == "1",
|
||||
)
|
||||
|
||||
@@ -70,7 +70,7 @@ class HttpResponse:
|
||||
|
||||
|
||||
def _request_sync(
|
||||
method: t.Literal["GET", "POST"],
|
||||
method: t.Literal["get", "post"],
|
||||
url: str,
|
||||
*,
|
||||
content: str | bytes | None = None,
|
||||
@@ -134,7 +134,7 @@ def _request_sync(
|
||||
|
||||
|
||||
async def request(
|
||||
method: t.Literal["GET", "POST"],
|
||||
method: t.Literal["get", "post"],
|
||||
url: str,
|
||||
*,
|
||||
content: bytes | None = None,
|
||||
@@ -158,7 +158,7 @@ async def request(
|
||||
|
||||
async def main() -> None:
|
||||
response = await request(
|
||||
"GET",
|
||||
"get",
|
||||
"https://postman-echo.com/get?foo=bar",
|
||||
)
|
||||
|
||||
|
||||
@@ -257,7 +257,7 @@ class UrlAsset(Asset):
|
||||
|
||||
async def try_fetch_as_blob(self) -> tuple[bytes, str | None]:
|
||||
try:
|
||||
response = await arequests.request("GET", str(self._url))
|
||||
response = await arequests.request("get", str(self._url))
|
||||
|
||||
content_type = response.headers.get("content-type")
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ class RioApi:
|
||||
self,
|
||||
endpoint: str,
|
||||
*,
|
||||
method: t.Literal["get", "post", "delete"] = "get",
|
||||
method: t.Literal["get", "post"] = "get",
|
||||
json: dict[str, t.Any] | None = None,
|
||||
file: t.BinaryIO | None = None,
|
||||
) -> t.Any:
|
||||
@@ -87,7 +87,7 @@ class RioApi:
|
||||
f"{BASE_URL}/{endpoint}",
|
||||
headers=headers,
|
||||
json=json,
|
||||
files=files,
|
||||
# files=files, # TODO:
|
||||
)
|
||||
|
||||
# Handle errors
|
||||
|
||||
@@ -29,15 +29,6 @@ from . import (
|
||||
webview_worker,
|
||||
)
|
||||
|
||||
try:
|
||||
from ...webview import webview
|
||||
except ImportError:
|
||||
if t.TYPE_CHECKING:
|
||||
from ...webview import webview
|
||||
else:
|
||||
webview = None
|
||||
|
||||
|
||||
# There is a hilarious problem with `watchfiles`: When a change occurs,
|
||||
# `watchfiles` logs that change. If Python is configured to log into the project
|
||||
# directory, then `watchfiles` will pick up on that new log line, thus
|
||||
@@ -188,7 +179,7 @@ class Arbiter:
|
||||
"""
|
||||
try:
|
||||
response = await arequests.request(
|
||||
"GET",
|
||||
"get",
|
||||
"https://pypi.org/pypi/rio-ui/json",
|
||||
)
|
||||
|
||||
@@ -429,11 +420,13 @@ class Arbiter:
|
||||
self._arbiter_task = asyncio.current_task()
|
||||
|
||||
# Make sure the webview module is available
|
||||
if self.run_in_window and webview is None:
|
||||
revel.fatal(
|
||||
"The `window` extra is required to run apps inside of a window."
|
||||
""" Run `pip install "rio-ui[[window]"` to install it."""
|
||||
)
|
||||
if self.run_in_window:
|
||||
try:
|
||||
from ... import webview_shim as webview_shim
|
||||
except ImportError:
|
||||
revel.fatal(
|
||||
"""The `window` extra is required to run apps inside of a window. Run `pip install "rio-ui[[window]"` to install it."""
|
||||
)
|
||||
|
||||
# Make sure the app is cleanly shut down, even if the arbiter crashes
|
||||
# for whichever reason.
|
||||
|
||||
@@ -4,14 +4,6 @@ import typing as t
|
||||
|
||||
from . import run_models
|
||||
|
||||
try:
|
||||
from ...webview import webview
|
||||
except ImportError:
|
||||
if t.TYPE_CHECKING:
|
||||
from ...webview import webview
|
||||
else:
|
||||
webview = None
|
||||
|
||||
|
||||
class WebViewWorker:
|
||||
def __init__(
|
||||
@@ -21,12 +13,14 @@ class WebViewWorker:
|
||||
debug_mode: bool,
|
||||
url: str,
|
||||
) -> None:
|
||||
from ... import webview_shim
|
||||
|
||||
self.push_event = push_event
|
||||
self.debug_mode = debug_mode
|
||||
self.url = url
|
||||
|
||||
# If running, this is the webview window
|
||||
self.window: webview.Window | None = None
|
||||
self.window: webview_shim.Window | None = None
|
||||
|
||||
def run(self) -> None:
|
||||
"""
|
||||
@@ -34,7 +28,8 @@ class WebViewWorker:
|
||||
`request_stop` is called. This function must be called from the main
|
||||
thread.
|
||||
"""
|
||||
assert webview is not None
|
||||
from ... import webview_shim
|
||||
|
||||
assert self.window is None, "Already running"
|
||||
|
||||
# Make sure this was called from the main thread.
|
||||
@@ -43,12 +38,12 @@ class WebViewWorker:
|
||||
), "Must be called from the main thread"
|
||||
|
||||
# Create the window
|
||||
self.window = webview.create_window(
|
||||
self.window = webview_shim.create_window(
|
||||
# TODO: Get the app's name, if possible
|
||||
"Rio (debug)" if self.debug_mode else "Rio",
|
||||
url=self.url,
|
||||
)
|
||||
webview.start()
|
||||
webview_shim.start()
|
||||
|
||||
# If we've reached this point, the window must have been closed.
|
||||
self.window = None
|
||||
|
||||
@@ -18,13 +18,6 @@ __all__ = [
|
||||
T = t.TypeVar("T")
|
||||
|
||||
|
||||
class NotGiven:
|
||||
pass
|
||||
|
||||
|
||||
NOT_GIVEN = NotGiven()
|
||||
|
||||
|
||||
@t.final
|
||||
@rio.docs.mark_constructor_as_private
|
||||
@dataclass
|
||||
@@ -135,7 +128,7 @@ class Dropdown(FundamentalComponent, t.Generic[T]):
|
||||
_: KW_ONLY
|
||||
label: str
|
||||
style: t.Literal["underlined", "rounded", "pill"]
|
||||
selected_value: T | utils.NotGiven = NOT_GIVEN
|
||||
selected_value: T | utils.NotGiven = utils.NOT_GIVEN
|
||||
is_sensitive: bool
|
||||
is_valid: bool
|
||||
on_change: rio.EventHandler[DropdownChangeEvent[T]]
|
||||
|
||||
@@ -851,7 +851,7 @@ class Layouter:
|
||||
round(self.window_width * pixels_per_unit),
|
||||
round(self.window_height * pixels_per_unit),
|
||||
),
|
||||
color="white",
|
||||
color="white", # type: ignore
|
||||
)
|
||||
|
||||
draw = PIL.ImageDraw.Draw(image)
|
||||
|
||||
@@ -637,11 +637,11 @@ window.resizeTo(screen.availWidth, screen.availHeight);
|
||||
# Close the tab / window
|
||||
if close_remote_session:
|
||||
if self.running_in_window:
|
||||
from .webview import webview
|
||||
from . import webview_shim
|
||||
|
||||
# It's possible that the session is being closed because the
|
||||
# user closed the window, so the window may not exist anymore
|
||||
window = webview.active_window()
|
||||
window = webview_shim.active_window()
|
||||
if window is not None:
|
||||
window.destroy()
|
||||
else:
|
||||
@@ -674,7 +674,7 @@ window.resizeTo(screen.availWidth, screen.availHeight);
|
||||
return low_level_root.content
|
||||
|
||||
async def _get_webview_window(self):
|
||||
from .webview import webview
|
||||
from . import webview_shim
|
||||
|
||||
assert (
|
||||
self.running_in_window
|
||||
@@ -682,7 +682,7 @@ window.resizeTo(screen.availWidth, screen.availHeight);
|
||||
|
||||
# The window may not have opened yet, so we'll wait until it exists
|
||||
while True:
|
||||
window = webview.active_window()
|
||||
window = webview_shim.active_window()
|
||||
|
||||
if window is not None:
|
||||
return window
|
||||
@@ -2023,9 +2023,7 @@ window.history.{method}(null, "", {json.dumps(str(active_page_url.relative()))})
|
||||
`title`: The new window title.
|
||||
"""
|
||||
if self.running_in_window:
|
||||
import webview.util # type: ignore
|
||||
|
||||
from .webview import webview
|
||||
from . import webview_shim
|
||||
|
||||
window = await self._get_webview_window()
|
||||
|
||||
@@ -2033,7 +2031,7 @@ window.history.{method}(null, "", {json.dumps(str(active_page_url.relative()))})
|
||||
try:
|
||||
window.set_title(title)
|
||||
break
|
||||
except webview.util.WebViewException:
|
||||
except webview_shim.util.WebViewException:
|
||||
await asyncio.sleep(0.2)
|
||||
else:
|
||||
await self._remote_set_title(title)
|
||||
@@ -2184,11 +2182,11 @@ window.history.{method}(null, "", {json.dumps(str(active_page_url.relative()))})
|
||||
# way to open a file dialog without blocking the event loop.
|
||||
import aiofiles
|
||||
|
||||
from .webview import webview
|
||||
from . import webview_shim
|
||||
|
||||
window = await self._get_webview_window()
|
||||
destinations = window.create_file_dialog(
|
||||
webview.SAVE_DIALOG,
|
||||
webview_shim.SAVE_DIALOG,
|
||||
directory="" if directory is None else str(directory),
|
||||
save_filename=file_name,
|
||||
)
|
||||
|
||||
23
rio/utils.py
23
rio/utils.py
@@ -1,6 +1,5 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import hashlib
|
||||
import mimetypes
|
||||
import os
|
||||
@@ -9,7 +8,6 @@ import secrets
|
||||
import socket
|
||||
import typing as t
|
||||
from dataclasses import dataclass
|
||||
from http.client import HTTPSConnection
|
||||
from io import BytesIO, StringIO
|
||||
from pathlib import Path
|
||||
|
||||
@@ -567,24 +565,3 @@ def soft_sort(
|
||||
|
||||
for element, _, _ in keyed_elements:
|
||||
elements.append(element)
|
||||
|
||||
|
||||
async def async_http_request(url: str) -> Tuple[Dict[str, str], bytes]:
|
||||
"""Performs an async HTTP GET request to the given URL and returns headers and content blob."""
|
||||
loop = asyncio.get_running_loop()
|
||||
host, path = url.split("/", 1)
|
||||
|
||||
def fetch() -> Tuple[Dict[str, str], bytes]:
|
||||
conn = HTTPSConnection(host)
|
||||
conn.request("GET", f"/{path}")
|
||||
response = conn.getresponse()
|
||||
headers = dict(response.getheaders())
|
||||
blob = response.read()
|
||||
conn.close()
|
||||
return headers, blob
|
||||
|
||||
return await loop.run_in_executor(None, fetch)
|
||||
|
||||
|
||||
# Example usage:
|
||||
# headers, blob = asyncio.run(async_http_request("example.com/some-path"))
|
||||
|
||||
@@ -1,4 +1,11 @@
|
||||
__all__ = ["webview"]
|
||||
__all__ = [
|
||||
"active_window",
|
||||
"create_window",
|
||||
"SAVE_DIALOG",
|
||||
"start",
|
||||
"util",
|
||||
"Window",
|
||||
]
|
||||
|
||||
|
||||
# There is an issue with `rye test`. rye passes a `--rootdir` argument to
|
||||
@@ -11,7 +18,14 @@ argv = sys.argv
|
||||
sys.argv = argv[:1]
|
||||
|
||||
try:
|
||||
import webview
|
||||
from webview import (
|
||||
SAVE_DIALOG,
|
||||
Window,
|
||||
active_window,
|
||||
create_window,
|
||||
start,
|
||||
util,
|
||||
)
|
||||
except ImportError:
|
||||
pass
|
||||
finally:
|
||||
Reference in New Issue
Block a user