Hot loading asset folder on dev (#643)
This commit is contained in:
parent
ae5b6426aa
commit
6e74cb00a3
55
poetry.lock
generated
55
poetry.lock
generated
@ -798,14 +798,14 @@ plugins = ["importlib-metadata"]
|
||||
|
||||
[[package]]
|
||||
name = "pyright"
|
||||
version = "1.1.296"
|
||||
version = "1.1.297"
|
||||
description = "Command line wrapper for pyright"
|
||||
category = "dev"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "pyright-1.1.296-py3-none-any.whl", hash = "sha256:51cc5f05807b1fb53f9f0e14736b8f772b500a3ba4e0edeb99727e68e700d9ea"},
|
||||
{file = "pyright-1.1.296.tar.gz", hash = "sha256:6c3cd394473e55a516ebe443d02b83e63456ef29f052dcf8e64e7875c1418fa6"},
|
||||
{file = "pyright-1.1.297-py3-none-any.whl", hash = "sha256:3fd6528280eb649f8b64b7ece55299f01e340d29f4cf257da876957e3ee24062"},
|
||||
{file = "pyright-1.1.297.tar.gz", hash = "sha256:89082de2fbd240fa75767b57824f4d8516f2fb9005047265a67b895547c6272f"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@ -1043,14 +1043,14 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "setuptools"
|
||||
version = "67.4.0"
|
||||
version = "67.5.1"
|
||||
description = "Easily download, build, install, upgrade, and uninstall Python packages"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "setuptools-67.4.0-py3-none-any.whl", hash = "sha256:f106dee1b506dee5102cc3f3e9e68137bbad6d47b616be7991714b0c62204251"},
|
||||
{file = "setuptools-67.4.0.tar.gz", hash = "sha256:e5fd0a713141a4a105412233c63dc4e17ba0090c8e8334594ac790ec97792330"},
|
||||
{file = "setuptools-67.5.1-py3-none-any.whl", hash = "sha256:1c39d42bda4cb89f7fdcad52b6762e3c309ec8f8715b27c684176b7d71283242"},
|
||||
{file = "setuptools-67.5.1.tar.gz", hash = "sha256:15136a251127da2d2e77ac7a1bc231eb504654f7e3346d93613a13f2e2787535"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
@ -1335,6 +1335,47 @@ typing-extensions = {version = "*", markers = "python_version < \"3.8\""}
|
||||
[package.extras]
|
||||
standard = ["colorama (>=0.4)", "httptools (>=0.5.0)", "python-dotenv (>=0.13)", "pyyaml (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "watchfiles (>=0.13)", "websockets (>=10.4)"]
|
||||
|
||||
[[package]]
|
||||
name = "watchdog"
|
||||
version = "2.3.1"
|
||||
description = "Filesystem events monitoring"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
files = [
|
||||
{file = "watchdog-2.3.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d1f1200d4ec53b88bf04ab636f9133cb703eb19768a39351cee649de21a33697"},
|
||||
{file = "watchdog-2.3.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:564e7739abd4bd348aeafbf71cc006b6c0ccda3160c7053c4a53b67d14091d42"},
|
||||
{file = "watchdog-2.3.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:95ad708a9454050a46f741ba5e2f3468655ea22da1114e4c40b8cbdaca572565"},
|
||||
{file = "watchdog-2.3.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a073c91a6ef0dda488087669586768195c3080c66866144880f03445ca23ef16"},
|
||||
{file = "watchdog-2.3.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:aa8b028750b43e80eea9946d01925168eeadb488dfdef1d82be4b1e28067f375"},
|
||||
{file = "watchdog-2.3.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:964fd236cd443933268ae49b59706569c8b741073dbfd7ca705492bae9d39aab"},
|
||||
{file = "watchdog-2.3.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:91fd146d723392b3e6eb1ac21f122fcce149a194a2ba0a82c5e4d0ee29cd954c"},
|
||||
{file = "watchdog-2.3.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:efe3252137392a471a2174d721e1037a0e6a5da7beb72a021e662b7000a9903f"},
|
||||
{file = "watchdog-2.3.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:85bf2263290591b7c5fa01140601b64c831be88084de41efbcba6ea289874f44"},
|
||||
{file = "watchdog-2.3.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8f2df370cd8e4e18499dd0bfdef476431bcc396108b97195d9448d90924e3131"},
|
||||
{file = "watchdog-2.3.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ea5d86d1bcf4a9d24610aa2f6f25492f441960cf04aed2bd9a97db439b643a7b"},
|
||||
{file = "watchdog-2.3.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:6f5d0f7eac86807275eba40b577c671b306f6f335ba63a5c5a348da151aba0fc"},
|
||||
{file = "watchdog-2.3.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b848c71ef2b15d0ef02f69da8cc120d335cec0ed82a3fa7779e27a5a8527225"},
|
||||
{file = "watchdog-2.3.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0d9878be36d2b9271e3abaa6f4f051b363ff54dbbe7e7df1af3c920e4311ee43"},
|
||||
{file = "watchdog-2.3.1-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:4cd61f98cb37143206818cb1786d2438626aa78d682a8f2ecee239055a9771d5"},
|
||||
{file = "watchdog-2.3.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:3d2dbcf1acd96e7a9c9aefed201c47c8e311075105d94ce5e899f118155709fd"},
|
||||
{file = "watchdog-2.3.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:03f342a9432fe08107defbe8e405a2cb922c5d00c4c6c168c68b633c64ce6190"},
|
||||
{file = "watchdog-2.3.1-py3-none-manylinux2014_aarch64.whl", hash = "sha256:7a596f9415a378d0339681efc08d2249e48975daae391d58f2e22a3673b977cf"},
|
||||
{file = "watchdog-2.3.1-py3-none-manylinux2014_armv7l.whl", hash = "sha256:0e1dd6d449267cc7d6935d7fe27ee0426af6ee16578eed93bacb1be9ff824d2d"},
|
||||
{file = "watchdog-2.3.1-py3-none-manylinux2014_i686.whl", hash = "sha256:7a1876f660e32027a1a46f8a0fa5747ad4fcf86cb451860eae61a26e102c8c79"},
|
||||
{file = "watchdog-2.3.1-py3-none-manylinux2014_ppc64.whl", hash = "sha256:2caf77ae137935c1466f8cefd4a3aec7017b6969f425d086e6a528241cba7256"},
|
||||
{file = "watchdog-2.3.1-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:53f3e95081280898d9e4fc51c5c69017715929e4eea1ab45801d5e903dd518ad"},
|
||||
{file = "watchdog-2.3.1-py3-none-manylinux2014_s390x.whl", hash = "sha256:9da7acb9af7e4a272089bd2af0171d23e0d6271385c51d4d9bde91fe918c53ed"},
|
||||
{file = "watchdog-2.3.1-py3-none-manylinux2014_x86_64.whl", hash = "sha256:8a4d484e846dcd75e96b96d80d80445302621be40e293bfdf34a631cab3b33dc"},
|
||||
{file = "watchdog-2.3.1-py3-none-win32.whl", hash = "sha256:a74155398434937ac2780fd257c045954de5b11b5c52fc844e2199ce3eecf4cf"},
|
||||
{file = "watchdog-2.3.1-py3-none-win_amd64.whl", hash = "sha256:5defe4f0918a2a1a4afbe4dbb967f743ac3a93d546ea4674567806375b024adb"},
|
||||
{file = "watchdog-2.3.1-py3-none-win_ia64.whl", hash = "sha256:4109cccf214b7e3462e8403ab1e5b17b302ecce6c103eb2fc3afa534a7f27b96"},
|
||||
{file = "watchdog-2.3.1.tar.gz", hash = "sha256:d9f9ed26ed22a9d331820a8432c3680707ea8b54121ddcc9dc7d9f2ceeb36906"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
watchmedo = ["PyYAML (>=3.10)"]
|
||||
|
||||
[[package]]
|
||||
name = "websockets"
|
||||
version = "10.4"
|
||||
@ -1433,4 +1474,4 @@ testing = ["big-O", "flake8 (<5)", "jaraco.functools", "jaraco.itertools", "more
|
||||
[metadata]
|
||||
lock-version = "2.0"
|
||||
python-versions = "^3.7"
|
||||
content-hash = "5ca32932250a2a3f00c95b0bdd77d9702b82e951958ee5ca29180f11174ac8e4"
|
||||
content-hash = "0ed6ff121b610ef2f2993889abbea9b3caa231f92964ab2fdc70667a814ad630"
|
||||
|
@ -43,6 +43,7 @@ from rich.prompt import Prompt
|
||||
|
||||
from pynecone import constants
|
||||
from pynecone.base import Base
|
||||
from pynecone.watch import AssetFolderWatch
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from pynecone.app import App
|
||||
@ -590,6 +591,16 @@ def posix_export(backend: bool = True, frontend: bool = True):
|
||||
os.system(cmd)
|
||||
|
||||
|
||||
def start_watching_assets_folder(root):
|
||||
"""Start watching assets folder.
|
||||
|
||||
Args:
|
||||
root: root path of the project.
|
||||
"""
|
||||
asset_watch = AssetFolderWatch(root)
|
||||
asset_watch.start()
|
||||
|
||||
|
||||
def setup_frontend(root: Path):
|
||||
"""Set up the frontend.
|
||||
|
||||
@ -622,6 +633,9 @@ def run_frontend(app: App, root: Path, port: str):
|
||||
# Set up the frontend.
|
||||
setup_frontend(root)
|
||||
|
||||
# start watching asset folder
|
||||
start_watching_assets_folder(root)
|
||||
|
||||
# Compile the frontend.
|
||||
app.compile(force_compile=True)
|
||||
|
||||
|
93
pynecone/watch.py
Normal file
93
pynecone/watch.py
Normal file
@ -0,0 +1,93 @@
|
||||
"""General utility functions."""
|
||||
|
||||
import contextlib
|
||||
import os
|
||||
import shutil
|
||||
import time
|
||||
|
||||
from watchdog.events import FileSystemEvent, FileSystemEventHandler
|
||||
from watchdog.observers import Observer
|
||||
|
||||
from pynecone.constants import APP_ASSETS_DIR, WEB_ASSETS_DIR
|
||||
|
||||
|
||||
class AssetFolderWatch:
|
||||
"""Asset folder watch class."""
|
||||
|
||||
def __init__(self, root):
|
||||
"""Initialize the Watch Class.
|
||||
|
||||
Args:
|
||||
root: root path of the public.
|
||||
"""
|
||||
self.path = str(root / APP_ASSETS_DIR)
|
||||
self.event_handler = AssetFolderHandler(root)
|
||||
|
||||
def start(self):
|
||||
"""Start watching asset folder."""
|
||||
self.observer = Observer()
|
||||
self.observer.schedule(self.event_handler, self.path, recursive=True)
|
||||
self.observer.start()
|
||||
|
||||
|
||||
class AssetFolderHandler(FileSystemEventHandler):
|
||||
"""Asset folder event handler."""
|
||||
|
||||
def __init__(self, root):
|
||||
"""Initialize the AssetFolderHandler Class.
|
||||
|
||||
Args:
|
||||
root: root path of the public.
|
||||
"""
|
||||
super().__init__()
|
||||
self.root = root
|
||||
|
||||
def on_modified(self, event: FileSystemEvent):
|
||||
"""Event handler when a file or folder was modified.
|
||||
This is called every time after a file is created, modified and deleted.
|
||||
|
||||
Args:
|
||||
event: Event information.
|
||||
"""
|
||||
dest_path = self.get_dest_path(event.src_path)
|
||||
|
||||
# wait 1 sec for fully saved
|
||||
time.sleep(1)
|
||||
|
||||
if os.path.isfile(event.src_path):
|
||||
with contextlib.suppress(PermissionError):
|
||||
shutil.copyfile(event.src_path, dest_path)
|
||||
if os.path.isdir(event.src_path):
|
||||
if os.path.exists(dest_path):
|
||||
shutil.rmtree(dest_path)
|
||||
with contextlib.suppress(PermissionError):
|
||||
shutil.copytree(event.src_path, dest_path)
|
||||
|
||||
def on_deleted(self, event: FileSystemEvent):
|
||||
"""Event hander when a file or folder was deleted.
|
||||
|
||||
Args:
|
||||
event: Event infomation.
|
||||
"""
|
||||
dest_path = self.get_dest_path(event.src_path)
|
||||
|
||||
if os.path.isfile(dest_path):
|
||||
# when event is about a file, pass
|
||||
# this will be deleted at on_modified function
|
||||
return
|
||||
|
||||
if os.path.exists(dest_path):
|
||||
shutil.rmtree(dest_path)
|
||||
|
||||
def get_dest_path(self, src_path: str) -> str:
|
||||
"""Get public file path.
|
||||
|
||||
Args:
|
||||
src_path: The asset file path.
|
||||
|
||||
Returns:
|
||||
The public file path.
|
||||
"""
|
||||
return src_path.replace(
|
||||
str(self.root / APP_ASSETS_DIR), str(self.root / WEB_ASSETS_DIR)
|
||||
)
|
@ -39,6 +39,7 @@ psutil = "^5.9.4"
|
||||
websockets = "^10.4"
|
||||
cloudpickle = "^2.2.1"
|
||||
python-multipart = "^0.0.5"
|
||||
watchdog = "^2.3.1"
|
||||
|
||||
[tool.poetry.group.dev.dependencies]
|
||||
pytest = "^7.1.2"
|
||||
|
Loading…
Reference in New Issue
Block a user