Merge pull request #724 from Textualize/css-path-relative

CSS Path Relative
This commit is contained in:
Will McGugan
2022-09-01 16:36:55 +01:00
committed by GitHub
4 changed files with 44 additions and 9 deletions

View File

@@ -10,5 +10,5 @@ class JustABox(App):
if __name__ == "__main__":
app = JustABox(css_path="just_a_box.css", watch_css=True)
app = JustABox(css_path="../darren/just_a_box.css", watch_css=True)
app.run()

30
src/textual/_path.py Normal file
View File

@@ -0,0 +1,30 @@
from __future__ import annotations
import inspect
import sys
from pathlib import Path, PurePath
def _make_path_object_relative(path: str | PurePath, obj: object) -> Path:
"""Convert the supplied path to a Path object that is relative to a given Python object.
If the supplied path is absolute, it will simply be converted to a Path object.
Used, for example, to return the path of a CSS file relative to a Textual App instance.
Args:
path (str | Path): A path.
obj (object): A Python object to resolve the path relative to.
Returns:
Path: A resolved Path object, relative to obj
"""
path = Path(path)
# If the path supplied by the user is absolute, we can use it directly
if path.is_absolute():
return path
# Otherwise (relative path), resolve it relative to obj...
subclass_module = sys.modules[obj.__module__]
subclass_path = Path(inspect.getfile(subclass_module))
resolved_path = (subclass_path.parent / path).resolve()
return resolved_path

View File

@@ -9,10 +9,9 @@ import sys
import warnings
from contextlib import redirect_stdout, redirect_stderr
from datetime import datetime
from pathlib import PurePath
from pathlib import PurePath, Path
from time import perf_counter
from typing import (
TYPE_CHECKING,
Any,
Generic,
Iterable,
@@ -25,6 +24,7 @@ from typing import (
from weakref import WeakSet, WeakValueDictionary
from ._ansi_sequences import SYNC_END, SYNC_START
from ._path import _make_path_object_relative
if sys.version_info >= (3, 8):
from typing import Literal
@@ -63,8 +63,6 @@ from .renderables.blank import Blank
from .screen import Screen
from .widget import Widget
if TYPE_CHECKING:
from .css.query import DOMQuery
PLATFORM = platform.system()
WINDOWS = PLATFORM == "Windows"
@@ -147,7 +145,7 @@ class App(Generic[ReturnType], DOMNode):
CSS = """
App {
background: $background;
color: $text-background;
color: $text-background;
}
"""
@@ -225,7 +223,15 @@ class App(Generic[ReturnType], DOMNode):
self.stylesheet = Stylesheet(variables=self.get_css_variables())
self._require_stylesheet_update: set[DOMNode] = set()
self.css_path = css_path or self.CSS_PATH
# We want the CSS path to be resolved from the location of the App subclass
css_path = css_path or self.CSS_PATH
if css_path is not None:
if isinstance(css_path, str):
css_path = Path(css_path)
css_path = _make_path_object_relative(css_path, self) if css_path else None
self.css_path = css_path
self._registry: WeakSet[DOMNode] = WeakSet()

View File

@@ -1,4 +1,3 @@
from __future__ import annotations
import os
from pathlib import PurePath
from typing import Callable
@@ -12,7 +11,7 @@ from ._callback import invoke
class FileMonitor:
"""Monitors a file for changes and invokes a callback when it does."""
def __init__(self, path: str | PurePath, callback: Callable) -> None:
def __init__(self, path: PurePath, callback: Callable) -> None:
self.path = path
self.callback = callback
self._modified = self._get_modified()