[API] Start accepting PathLike objects here and there

This commit is contained in:
Olivier Philippon
2022-05-04 10:02:00 +01:00
parent 7ae4c73a7a
commit 3f09af3768
8 changed files with 37 additions and 21 deletions

View File

@@ -141,9 +141,12 @@ class BasicApp(App):
self.panic(self.tree)
css_file = Path(__file__).parent / "basic.css"
sandbox_folder = Path(__file__).parent
app = BasicApp(
css_file=str(css_file), watch_css=True, log="textual.log", log_verbosity=0
css_file=sandbox_folder / "basic.css",
watch_css=True,
log=sandbox_folder / "textual.log",
log_verbosity=0,
)
if __name__ == "__main__":

View File

@@ -141,8 +141,12 @@ class BasicApp(App):
self.panic(self.tree)
css_file = Path(__file__).parent / "basic.css"
app = BasicApp(css_file=str(css_file), watch_css=True, log="textual.log")
sandbox_folder = Path(__file__).parent
app = BasicApp(
css_file=sandbox_folder / "basic.css",
watch_css=True,
log=sandbox_folder / "textual.log",
)
if __name__ == "__main__":
app.run()

View File

@@ -7,6 +7,7 @@ import platform
import sys
import warnings
from contextlib import redirect_stdout
from pathlib import PurePath
from time import perf_counter
from typing import (
Any,
@@ -105,20 +106,20 @@ class App(Generic[ReturnType], DOMNode):
def __init__(
self,
driver_class: Type[Driver] | None = None,
log: str = "",
log: str | PurePath = "",
log_verbosity: int = 1,
title: str = "Textual Application",
css_file: str | None = None,
css_file: str | PurePath | None = None,
watch_css: bool = True,
):
"""Textual application base class
Args:
driver_class (Type[Driver] | None, optional): Driver class or ``None`` to auto-detect. Defaults to None.
log (str, optional): Path to log file, or "" to disable. Defaults to "".
log (str | PurePath, optional): Path to log file, or "" to disable. Defaults to "".
log_verbosity (int, optional): Log verbosity from 0-3. Defaults to 1.
title (str, optional): Default title of the application. Defaults to "Textual Application".
css_file (str | None, optional): Path to CSS or ``None`` for no CSS file. Defaults to None.
css_file (str | PurePath | None, optional): Path to CSS or ``None`` for no CSS file. Defaults to None.
watch_css (bool, optional): Watch CSS for changes. Defaults to True.
"""
# N.B. This must be done *before* we call the parent constructor, because MessagePump's

View File

@@ -1,6 +1,7 @@
from __future__ import annotations
from functools import lru_cache
from pathlib import PurePath
from typing import Iterator, Iterable
from rich import print
@@ -305,7 +306,7 @@ def substitute_references(
def parse(
css: str, path: str, variables: dict[str, str] | None = None
css: str, path: str | PurePath, variables: dict[str, str] | None = None
) -> Iterable[RuleSet]:
"""Parse CSS by tokenizing it, performing variable substitution,
and generating rule sets from it.

View File

@@ -3,7 +3,7 @@ from __future__ import annotations
import os
from collections import defaultdict
from operator import itemgetter
from pathlib import Path
from pathlib import Path, PurePath
from typing import cast, Iterable
import rich.repr
@@ -149,13 +149,13 @@ class Stylesheet:
"""
self.variables = variables
def _parse_rules(self, css: str, path: str) -> list[RuleSet]:
def _parse_rules(self, css: str, path: str | PurePath) -> list[RuleSet]:
"""Parse CSS and return rules.
Args:
css (str): String containing Textual CSS.
path (str): Path to CSS or unique identifier
path (str | PurePath): Path to CSS or unique identifier
Raises:
StylesheetError: If the CSS is invalid.
@@ -171,11 +171,11 @@ class Stylesheet:
raise StylesheetError(f"failed to parse css; {error}")
return rules
def read(self, filename: str) -> None:
def read(self, filename: str | PurePath) -> None:
"""Read Textual CSS file.
Args:
filename (str): filename of CSS.
filename (str | PurePath): filename of CSS.
Raises:
StylesheetError: If the CSS could not be read.
@@ -188,15 +188,16 @@ class Stylesheet:
path = os.path.abspath(filename)
except Exception as error:
raise StylesheetError(f"unable to read {filename!r}; {error}")
self.source[path] = css
self.source[str(path)] = css
self._require_parse = True
def add_source(self, css: str, path: str | None = None) -> None:
def add_source(self, css: str, path: str | PurePath | None = None) -> None:
"""Parse CSS from a string.
Args:
css (str): String with CSS source.
path (str, optional): The path of the source if a file, or some other identifier. Defaults to "".
path (str | PurePath, optional): The path of the source if a file, or some other identifier.
Defaults to None.
Raises:
StylesheetError: If the CSS could not be read.
@@ -205,6 +206,8 @@ class Stylesheet:
if path is None:
path = str(hash(css))
elif isinstance(path, PurePath):
path = str(css)
if path in self.source and self.source[path] == css:
# Path already in source, and CSS is identical
return

View File

@@ -1,6 +1,7 @@
from __future__ import annotations
import re
from pathlib import PurePath
from typing import Iterable
from textual.css.tokenizer import Expect, Tokenizer, Token
@@ -136,7 +137,7 @@ class TokenizerState:
"declaration_set_end": expect_root_scope,
}
def __call__(self, code: str, path: str) -> Iterable[Token]:
def __call__(self, code: str, path: str | PurePath) -> Iterable[Token]:
tokenizer = Tokenizer(code, path=path)
expect = self.EXPECT
get_token = tokenizer.get_token

View File

@@ -1,6 +1,7 @@
from __future__ import annotations
import re
from pathlib import PurePath
from typing import NamedTuple
from rich.console import Group, RenderableType
@@ -148,8 +149,8 @@ class Token(NamedTuple):
class Tokenizer:
def __init__(self, text: str, path: str = "") -> None:
self.path = path
def __init__(self, text: str, path: str | PurePath = "") -> None:
self.path = str(path)
self.code = text
self.lines = text.splitlines(keepends=True)
self.line_no = 0

View File

@@ -1,4 +1,6 @@
from __future__ import annotations
import os
from pathlib import PurePath
from typing import Callable
import rich.repr
@@ -8,7 +10,7 @@ from ._callback import invoke
@rich.repr.auto
class FileMonitor:
def __init__(self, path: str, callback: Callable) -> None:
def __init__(self, path: str | PurePath, callback: Callable) -> None:
self.path = path
self.callback = callback
self._modified = self._get_modified()