Source code for httk.serve.web.api

"""Expose high-level helpers for serving and publishing web sites."""

from pathlib import Path

from httk.serve.http import ServeApp

from .engine.site_engine import SiteEngine
from .model.config import SiteConfig
from .model.page import PublishReport
from .publishing.static import publish_site
from .runtime.asgi import create_app
from .runtime.devserver import run_dev_server


[docs] def create_asgi_app( srcdir: str | Path, *, baseurl: str | None = None, compatibility_mode: bool = False, config_name: str = "config", debug: bool = False, table_token_secret: str | bytes | None = None, ) -> ServeApp: """Create an ASGI application for a site source directory. :param srcdir: Site source directory. :param baseurl: Optional site base URL used when building links. :param compatibility_mode: Whether to use legacy site conventions. :param config_name: Configuration module name. :param debug: Whether to enable Starlette debug responses. :param table_token_secret: Secret used to authenticate table continuation tokens. :return: Configured serving application. """ config = SiteConfig.from_srcdir( srcdir=srcdir, baseurl=baseurl, compatibility_mode=compatibility_mode, config_name=config_name, ) engine = SiteEngine(config, table_token_secret=table_token_secret) try: return create_app(engine=engine, debug=debug) except BaseException as exc: _close_after_operation_error(engine, exc) raise
[docs] def serve( srcdir: str | Path, *, host: str = "127.0.0.1", port: int = 8080, baseurl: str | None = None, compatibility_mode: bool = False, config_name: str = "config", debug: bool = False, table_token_secret: str | bytes | None = None, ) -> None: """Run a development server for a site source directory. :param srcdir: Site source directory. :param host: Interface on which to listen. :param port: TCP port on which to listen. :param baseurl: Optional site base URL used when building links. :param compatibility_mode: Whether to use legacy site conventions. :param config_name: Configuration module name. :param debug: Whether to enable Starlette debug responses. :param table_token_secret: Secret used to authenticate table continuation tokens. """ app = create_asgi_app( srcdir=srcdir, baseurl=baseurl, compatibility_mode=compatibility_mode, config_name=config_name, debug=debug, table_token_secret=table_token_secret, ) try: run_dev_server(app=app, host=host, port=port) except BaseException as exc: _close_after_operation_error(app.state.engine, exc) raise app.state.engine.close()
[docs] def publish( srcdir: str | Path, outdir: str | Path, baseurl: str, *, host_static: str | None = None, compatibility_mode: bool = False, config_name: str = "config", use_urls_without_ext: bool | None = None, ) -> PublishReport: """Render a site source directory into static output files. :param srcdir: Site source directory. :param outdir: Destination directory for published files. :param baseurl: Site base URL used when building links. :param host_static: Optional host URL for static assets. :param compatibility_mode: Whether to use legacy site conventions. :param config_name: Configuration module name. :param use_urls_without_ext: Whether published page links omit extensions. :return: Report of files written and rendering warnings. """ publish_use_urls_without_ext = use_urls_without_ext if use_urls_without_ext is not None else not compatibility_mode config = SiteConfig.from_srcdir( srcdir=srcdir, baseurl=baseurl, host_static=host_static, compatibility_mode=compatibility_mode, config_name=config_name, publish_use_urls_without_ext=publish_use_urls_without_ext, ) engine = SiteEngine(config) try: report = publish_site(engine=engine, outdir=outdir) except BaseException as exc: _close_after_operation_error(engine, exc) raise engine.close() return report
def _close_after_operation_error(engine: SiteEngine, operation_error: BaseException) -> None: """Release an engine without concealing the operation that failed first.""" try: engine.close() except BaseException as cleanup_error: operation_error.add_note(f"Additional site resource cleanup failure: {cleanup_error!r}")