diff --git a/.forgejo/workflows/ci.yml b/.forgejo/workflows/ci.yml index 11d4935..a207a4f 100644 --- a/.forgejo/workflows/ci.yml +++ b/.forgejo/workflows/ci.yml @@ -1,10 +1,14 @@ -on: [push, pull_request] +on: + push: + branches: [main] + pull_request: jobs: static-analysis: runs-on: runner-latest steps: - uses: actions/checkout@v4 + - uses: https://github.com/astral-sh/setup-uv@v3 - name: Linting run: pipx run pre-commit run ruff -a - name: Format @@ -13,6 +17,11 @@ jobs: run: pipx run pre-commit run check-yaml -a - name: Validate shell scripts run: pipx run pre-commit run shellcheck -a + - name: Check types + run: | + uv venv + uv pip install . + pipx run pre-commit run pyright -a export-trace: runs-on: runner-latest needs: [static-analysis] diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 62d2243..3942f1b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -13,3 +13,7 @@ repos: hooks: - id: ruff - id: ruff-format + - repo: https://github.com/RobertCraigie/pyright-python + rev: v1.1.389 + hooks: + - id: pyright diff --git a/blogue/build.py b/blogue/build.py index 747e23b..21bd64e 100644 --- a/blogue/build.py +++ b/blogue/build.py @@ -13,7 +13,7 @@ def build_site( *, client: DocumentClient, renderer: DocumentRenderer, - destination_path: str | None = None, + destination_path: str | pathlib.Path | None = None, ): """ Build HTML documents from data extracted from the given client, using @@ -44,13 +44,15 @@ def build_site( docs.extend(current_document.children) continue + current_path = current_document.path or "" + target_path = destination_path.joinpath( - pathlib.Path(current_document.path).stem + ".html" + pathlib.Path(current_path).stem + ".html" ) with open(target_path, "w") as out: rendered = renderer.render( - current_metadata["template"], + str(current_metadata["template"]), { **current_metadata, "site": site_metadata, diff --git a/blogue/models.py b/blogue/models.py index 4de6fcb..4c36889 100644 --- a/blogue/models.py +++ b/blogue/models.py @@ -1,5 +1,6 @@ import pydantic +import typing import abc @@ -12,7 +13,7 @@ class Document(pydantic.BaseModel, abc.ABC): @property @abc.abstractmethod - def metadata(self) -> dict[str, str]: + def metadata(self) -> dict[str, object]: """Metadata associated with the document.""" @property @@ -47,4 +48,4 @@ class DocumentRenderer(abc.ABC): """Renders documents into HTML.""" @abc.abstractmethod - def render(self, template_path: str, content: dict[str, str]) -> str: ... + def render(self, template_path: str, content: dict[str, typing.Any]) -> str: ... diff --git a/blogue/nextcloud.py b/blogue/nextcloud.py index 1a1975b..1b0ef44 100644 --- a/blogue/nextcloud.py +++ b/blogue/nextcloud.py @@ -22,7 +22,7 @@ class NextCloudDocument(Document): type: str @functools.cached_property - def _parsed_markdown(self) -> tuple[dict[str, str], str]: + def _parsed_markdown(self) -> tuple[dict[str, object], str]: try: return frontmatter.parse(self.raw) except Exception as e: @@ -30,7 +30,7 @@ class NextCloudDocument(Document): return tuple() @property - def metadata(self) -> dict[str, str]: + def metadata(self) -> dict[str, object]: return self._parsed_markdown[0] @property @@ -68,7 +68,10 @@ class NextCloudClient(DocumentClient, arbitrary_types_allowed=True): root_document = NextCloudDocument(path=root_path, type="collection") for r in root_properties: - doc_path = r.find("{DAV:}href").text + doc_path = r.find("{DAV:}href") + + if doc_path is not None: + doc_path = doc_path.text if doc_path == root_document.path: continue diff --git a/blogue/renderer.py b/blogue/renderer.py index 31769bb..44cd245 100644 --- a/blogue/renderer.py +++ b/blogue/renderer.py @@ -2,6 +2,8 @@ from .models import DocumentRenderer import jinja2 +import typing + class JinjaDocumentRenderer(DocumentRenderer): """Renders documents using Jinja templates.""" @@ -12,7 +14,7 @@ class JinjaDocumentRenderer(DocumentRenderer): loader=jinja2.FileSystemLoader(searchpath="./templates") ) - def render(self, template_path: str, content: dict[str, str]) -> str: + def render(self, template_path: str, content: dict[str, typing.Any]) -> str: t = self._environment.get_template(template_path) return t.render(**content) diff --git a/pyproject.toml b/pyproject.toml index 07dc7bb..6627517 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,7 +3,7 @@ name = "blogue" version = "0.1.0" description = "Basic static site generator that powers my blog." readme = "README.md" -requires-python = ">=3.12" +requires-python = ">=3.11" dependencies = [ "click>=8.1.7", "httpx>=0.27.2", @@ -24,3 +24,7 @@ dev-dependencies = [ "pre-commit>=4.0.1", "ruff>=0.7.1", ] + +[tool.pyright] +venvPath = "." +venv = ".venv"