Skip to content

Commit

Permalink
trigger failed page reloads for chromium based browsers
Browse files Browse the repository at this point in the history
  • Loading branch information
shravanasati committed May 22, 2024
1 parent 287e833 commit 3770c1c
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 8 deletions.
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,22 +91,24 @@ This yaml file comes with a schema which can be utilized by yaml language server
Let's quickly go over the config options:
- **`browser`**: This option specifies the browser to use when `url` is given. The only valid options for browser currently are `firefox` and `chrome`.
- **`browser`**: This option specifies the browser to use when `url` is given. The only valid options for browser currently are `firefox`, `chrome`, `edge` and `safari`.

- **`include_only`**: The list of gitignore-style patterns to consider for live reload. This will be used along with the ignore file (`stella.ignore` or `.gitignore`) to match files. eg. `include_only: ["*.py", "*.env"]`.

- **`poll_interval`**: The duration in **milliseconds** to poll the filesystem for changes.
- **`poll_interval`**: The duration in **milliseconds** to poll the filesystem for changes. This has been modified past v0.3.0 - it now signifies the threshold duration for which stella should accept changes.

- **`browser_wait_interval`**: This is the duration in **milliseconds** between the execution of given command on the terminal and browser page refresh. This can be used in situations when the server takes some time before it is ready to listen on a given port.

- **`follow_symlinks`**: Boolean value that indicates whether to follow symbolic links encountered in the filesystem.
<!-- - **`follow_symlinks`**: Boolean value that indicates whether to follow symbolic links encountered in the filesystem. -->

- **`scripts`**: This the list of npm style scripts that take 4 parameters each.

* `name`: Name of the script. To execute a certain script, use its name in the `stella run SCRIPT_NAME` command. The script named _default_ will be used in case SCRIPT_NAME is not provided. Note that this parameter is **case-insensitive**, for convenience.

* `url`: The URL to listen to on the browser. Set it to an empty string (`''`) if you don't want live reload on the browser. eg. `localhost:8000`.

> Note: For chrome and edge, you must prepend the localhost URL with `http://`. Not tested on safari, but if you see `data;` in the address bar, this URL change should fix it.

* `command`: A single command or a list of commands to execute on the terminal. eg.
```
command: python3 app.py
Expand Down
4 changes: 2 additions & 2 deletions stella.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# yaml-language-server: $schema=https://raw.githubusercontent.com/shravanasati/stellapy/master/schema.json

browser: "firefox"
browser: edge
include_only: ["*.py"]
poll_interval: 500
browser_wait_interval: 1000
Expand All @@ -25,6 +25,6 @@ scripts:
command: ls

- name: server
url: "localhost:8000"
url: "http://localhost:8000"
shell: false
command: python -m http.server
22 changes: 19 additions & 3 deletions stellapy/reloader.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
from typing import Any, Callable, Generic, TypeVar

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.common.exceptions import NoSuchElementException
from watchdog.observers import Observer

from stellapy.configuration import Configuration
Expand Down Expand Up @@ -134,7 +136,7 @@ def _trigger_executor(self):
self.trigger_queue.execute_remaining()
sleep(self.trigger_execution_interval)

def start_browser(self):
def _start_browser(self):
# selenium driver
if self.config.browser not in ("firefox", "chrome", "safari", "edge"):
# this should never happen because of configuration validation
Expand All @@ -154,8 +156,8 @@ def start_browser(self):

try:
# todo handle selenium manager exception
# todo edit schema.json
self.driver.get(self.url)

except Exception as e:
if "Message: unknown error: cannot find Chrome binary" in str(e):
log(
Expand All @@ -176,6 +178,20 @@ def _browser_reloader(self, _: Trigger[timedelta]):
A helper function used in browser reload triggers.
"""
self.driver.refresh()
# firefox throws an error via selenium if the refresh wasn't successfull
# chrome and edge don't, so we can't call the error handler function (exponential backoff)
# even if the page wasn't loaded
# thus, check if the body tag has `neterror` class because it's always present
# when any browser(again, not tested for safari) shows the error page
# not sure how safari behaves, so we'll check for it too
if self.config.browser != "firefox":
try:
el = self.driver.find_element(By.CLASS_NAME, "neterror")
except NoSuchElementException:
return
else:
if el.tag_name == "body":
raise Exception("failed to load page")

@staticmethod
def _displayable_seconds_from_timedelta(t: timedelta):
Expand Down Expand Up @@ -327,7 +343,7 @@ def start(self) -> None:
input_thread.start()
self.executor.start()
if self.RELOAD_BROWSER:
self.start_browser()
self._start_browser()

self.observer.start()
# self.restart()

0 comments on commit 3770c1c

Please sign in to comment.